home *** CD-ROM | disk | FTP | other *** search
/ Aminet 12 / Aminet 12 (1996)(GTI - Schatztruhe)[!][Jun 1996].iso / Aminet / misc / unix / adtf.lha / adtf.c
C/C++ Source or Header  |  1996-03-14  |  81KB  |  4,179 lines

  1. #if 0 
  2.  
  3.  ############################################################################
  4.  ##                                                                        ##
  5.  ## This is ADT 2.01, a user friendly frontend for all Aminet FTP sites.It ##
  6.  ## can be compiled easily on any UNIX flavor and AmigaDOS. Under UNIX,    ##
  7.  ## compile it using the command                                           ##
  8.  ##                                                                        ##
  9.  ##   sh adt.c            (you may append flags, e.g. sh adt.c -DNO_FTP)   ##
  10.  ##                                                                        ##
  11.  ## See adt.c.readme for further notes                                     ##
  12.  ##                                                                        ##
  13.  ##     --------- Nouvelle version partiellement francisee ----------      ##
  14.  ##     Comme j en avait marre d avoir une version non francaise de ce     ##
  15.  ##     superbe programme je me suis mis a sa traduction. Bien entendu,    ##
  16.  ##     il reste des termes anglais mais c est seulement par manque de     ##
  17.  ##     temps. Le principal (Les ecrans les plus utilises) a ete           ##
  18.  ##     traduit. De plus, j ai rajoute une commande dans le script         ##
  19.  ##     de compilation pour pouvoir choisir son compilateur et aussi       ##
  20.  ##     empecher sous Solaris 2.4 un bug de plantage systematique          ##
  21.  ##     lorsque l on utilise l optimisation de gcc  ... Voila.             ##
  22.  ##         Allez faites   sh adtf.c  et vogue la galere!                  ##
  23.  ##    PS: cette version contient les nouvelles adresses des sites         ##
  24.  ##        francais habituel cnam et ftp.grolier.fr                        ## 
  25.  ############################################################################
  26.  
  27.  
  28.  cc="gcc"
  29.  libs="-lcurses -ltermcap"
  30.  for i in /usr/lib/libsocket* ; do if [ -r $i ] ; then  # Kludge for systems
  31.   libs="$libs -lsocket -lnsl" ; break                   # with bash as /bin/sh
  32.  fi ; done                                              # like NetBSD or Linux
  33.  
  34.  if [ `uname -s`  =  'SunOS' ] && [ `uname -r`  = '5.4' ]
  35.  then 
  36.  echo $cc -s -o adt_f $* $0 $libs
  37.  exec $cc -s -o adt_f $* $0 $libs
  38.  else 
  39.  echo $cc -O -s -o adt $* $0 $libs
  40.  exec $cc -O -s -o adt $* $0 $libs
  41.  fi
  42.  exit
  43. #endif
  44.  
  45. #include <stdio.h>
  46.  
  47. #ifdef AMIGA
  48. # define getchr getch
  49. # define makedir(x,y) mkdir(x)
  50. # define popen(x,y) stdout
  51. # define pclose(x)
  52. # define sleep(x)
  53. # define COPYCMD "copy"
  54. # define CURDIR "\"\""
  55. # define TEMPPATH "t:"
  56. # define NO_FTP
  57. # define NO_FIND_CLIENT
  58. # define _system(x) puts(x)
  59. #else
  60. # define getchr getchar
  61. # define makedir(x,y) mkdir(x,y)
  62. # define COPYCMD "cp"
  63. # define CURDIR "."
  64. # define TEMPPATH "/tmp/"
  65. #endif
  66.  
  67. #ifdef NO_FTP
  68. # define NO_BUILTIN_FTP
  69. # define NO_EXTERNAL_FTP
  70. #endif
  71.  
  72. #ifdef NO_BUILTIN_FTP
  73. # ifdef NO_FIND_CLIENT
  74. #  define NO_TCP_UTILITY
  75. # endif
  76. #else /* !NO_BUILTIN_FTP */
  77. # define NO_EXTERNAL_FTP
  78. #endif
  79.  
  80. /*---------------------------------INCLUDES---------------------------------*/
  81. #define _INCLUDE_POSIX_SOURCE
  82.  
  83. #ifndef AMIGA
  84. # include <sys/types.h>
  85.  
  86. # ifdef DEBUG
  87. #  include <stdlib.h>
  88. #  include <unistd.h>
  89. #  include <string.h>
  90. #  include <sys/param.h>
  91. #  include <sys/stat.h>
  92. # endif
  93.  
  94. # ifndef NO_EXTERNAL_FTP
  95. #  include <sys/stat.h>
  96. # endif
  97.  
  98. # ifndef NO_TCP_UTILITY
  99. #  include <sys/file.h>
  100. #  include <stdio.h>
  101. #  include <netdb.h>
  102. #  include <sys/socket.h>
  103. #  include <netinet/in.h>
  104. #  include <arpa/inet.h>
  105. # endif
  106. #endif
  107.  
  108. #ifndef NO_CURSES
  109. # include <curses.h>
  110. #endif
  111.  
  112. #include <signal.h>
  113. /*---------------------------------GLOBALS-----------------------------------*/
  114.  
  115. #define E_FILE 20
  116. #define E_DIR  10
  117. #define E_DESC 44
  118.  
  119. #define K_CTRL -'@'
  120.  
  121. struct adt_entry {
  122.   long time;
  123.   long size;
  124.   long readmesize;
  125.   short version;
  126.   char readmelen;
  127.   char tagged;
  128.   char osversion;
  129.   char status;
  130.   char file[E_FILE + 1];
  131.   char dir[E_DIR + 1];
  132.   char desc[E_DESC + 1];
  133. };
  134. #define ENTRY struct adt_entry
  135.  
  136. #define STATUS_LOCAL  0
  137. #define STATUS_REMOTE 1
  138.  
  139.  
  140. struct adt_list {
  141.   ENTRY **list;
  142.   char *(*disp) ();
  143.   int mem;
  144.   int num;
  145.   int offset;
  146.   int current;
  147.   char type;
  148.   char top;
  149.   char *sel;
  150.   char *sort;
  151.   char *cmds;
  152. };
  153. #define LIST struct adt_list
  154.  
  155.  
  156. struct adt_transfer {
  157.   char *name;
  158.   char *text;
  159.   int (*init) ();
  160. };
  161. #define TRANSFER struct adt_transfer
  162.  
  163. extern TRANSFER TransferTypes[];
  164.  
  165.  
  166. LIST AllFiles, VisibleFiles, Marked, Alternate;
  167. LIST *File = &AllFiles, *Vis = &VisibleFiles, *Mark = &Marked, *Alt = &Alternate;
  168.  
  169. int Dispmode;
  170. int Width = 80, Height = 25;
  171. int LastCall;
  172. char *NoFilesString = "Pas de fichiers disponible";
  173. char HomeDir[250];
  174. char UserName[50] = "user";
  175. char ConfigFile[200] = ".adtrc";
  176. char *FindDesc = "Recherche d'une chaine sans la casse";
  177. char GotComplete, GotLocal, GotRecent;
  178. char Flat, Readme, Silent, Path[250], Action;
  179. char InitialSetup;
  180. char Connected;
  181. char MaskSIGINT, GotSIGINT;
  182.  
  183. int (*disp_init) ();
  184. int (*disp_cleanup) ();
  185. int (*disp_choice) ();
  186. int (*disp_mainloop) ();
  187. int (*disp_report) ();
  188. int (*disp_status) ();
  189. int (*disp_confirm) ();
  190. int (*disp_more) ();
  191. int (*disp_getchar) ();
  192. int (*disp_refresh) ();
  193. int (*disp_clear) ();
  194. char *(*disp_inputstr) ();
  195.  
  196. int (*trans_options) ();
  197. int (*trans_connect) ();
  198. int (*trans_remopen) ();
  199. int (*trans_download) ();
  200. int (*trans_disconnect) ();
  201. int (*trans_close) ();
  202.  
  203. /*----------------------------main exit point--------------------------------*/
  204. int exit_adt(err)
  205.   char *err;
  206. {
  207.   if (disp_cleanup)
  208.     disp_cleanup();
  209.  
  210.   if (trans_close)
  211.     trans_close();
  212.  
  213.   if (err)
  214.     puts(err);
  215.  
  216.   exit(err ? 20 : 0);
  217.  
  218.   return 0;
  219. }
  220.  
  221. /*--------------------------quick entry allocator----------------------------*/
  222. #define CHUNKALLOC 100
  223.  
  224. struct EntryChunk {
  225.   struct EntryChunk *next;
  226.   ENTRY chunks[CHUNKALLOC];
  227. };
  228. #define CHUNK struct EntryChunk
  229.  
  230. int InCount;
  231. CHUNK *EntryChunk, *ChunkList;
  232.  
  233. char *salloc(len)
  234.   int len;
  235. {
  236.   char *t;
  237.  
  238.   if (!(t = (char *) malloc(len)))
  239.     exit_adt("Problème de mémoire\n");
  240.  
  241.   return t;
  242. }
  243.  
  244.  
  245. ENTRY *e_alloc()
  246. {
  247.   if (!InCount) {
  248.     InCount = CHUNKALLOC;
  249.     EntryChunk = (CHUNK *) salloc(sizeof(CHUNK));
  250.     EntryChunk->next = ChunkList;
  251.     ChunkList = EntryChunk;
  252.   }
  253.   return EntryChunk->chunks + --InCount;
  254. }
  255.  
  256. int e_add(l, e)
  257.   LIST *l;
  258.   ENTRY *e;
  259. {
  260.   ENTRY **oldlist;
  261.   int i;
  262.  
  263.   if (!l->mem) {
  264.     l->mem = 100;
  265.  
  266.     l->list = (ENTRY **) salloc(l->mem * sizeof(ENTRY *));
  267.   }
  268.   if (l->num == l->mem) {
  269.     oldlist = l->list;
  270.  
  271.     l->list = (ENTRY **) salloc(2 * l->mem * sizeof(ENTRY *));
  272.  
  273.     for (i = 0; i < l->num; i++)
  274.       l->list[i] = oldlist[i];
  275.  
  276.     l->mem *= 2;
  277.     free(oldlist);
  278.   }
  279.   l->list[l->num++] = e;
  280.   return 0;
  281. }
  282.  
  283. int l_reset(l)
  284.   LIST *l;
  285. {
  286.   if (l->list)
  287.     free(l->list);
  288.   l->list = 0;
  289.   l->mem = 0;
  290.   l->num = 0;
  291.   l->current = 0;
  292.   return 0;
  293. }
  294.  
  295. int l_store()
  296. {
  297.   int i;
  298.   ENTRY **e1, **e2;
  299.  
  300.   if (Alt->list)
  301.     free(Alt->list);
  302.  
  303.   if (Vis->mem)
  304.     Alt->list = (ENTRY **) salloc(Vis->mem * sizeof(ENTRY *));
  305.  
  306.   for (i = Vis->num - 1, e1 = Vis->list, e2 = Alt->list; i >= 0; i--)
  307.     *e2++ = *e1++;
  308.  
  309.   Alt->list = Vis->list;
  310.   Alt->num = Vis->num;
  311.   Alt->mem = Vis->mem;
  312.   Alt->offset = Vis->offset;
  313.   Alt->current = Vis->current;
  314.   Alt->sel = Vis->sel;
  315.   Alt->sort = Vis->sort;
  316.  
  317.   return 0;
  318. }
  319.  
  320. int e_freeall()
  321. {
  322.   CHUNK *c, *next;
  323.  
  324.   l_reset(Alt);
  325.   l_reset(Mark);
  326.   l_reset(Vis);
  327.   l_reset(File);
  328.  
  329.   for (c = ChunkList; c; c = next) {
  330.     next = c->next;
  331.     free(c);
  332.   }
  333.   ChunkList = 0;
  334.   InCount = 0;
  335.   GotComplete = GotLocal = GotRecent = 0;
  336.  
  337.   return 0;
  338. }
  339.  
  340. /*-------------------------string funcs for portability----------------------*/
  341. int mystrlen(s)
  342.   char *s;
  343. {
  344.   int n = 0;
  345.  
  346.   while (*s++)
  347.     n++;
  348.   return n;
  349. }
  350.  
  351. int mystrncpy(s1, s2, n)
  352.   char *s1, *s2;
  353.   int n;
  354. {
  355.   while (*s2 && n--)
  356.     *s1++ = *s2++;
  357.  
  358.   *s1++ = 0;
  359.  
  360.   return 0;
  361. }
  362.  
  363. char *mystrcpy(s1, s2)
  364.   char *s1, *s2;
  365. {
  366.   char *t = s1;
  367.  
  368.   while ((*s1++ = *s2++));
  369.  
  370.   return t;
  371. }
  372.  
  373. int mystrcmp(s1, s2)
  374.   char *s1, *s2;
  375. {
  376.   while (*s1 == *s2 && *s1)
  377.     s1++, s2++;
  378.  
  379.   return *s1 - *s2;
  380. }
  381.  
  382. #define LOWER(x) (x<='Z' && x>='A' ? x-'A'+'a' : x)
  383.  
  384. int mystricmp(s1, s2)
  385.   char *s1, *s2;
  386. {
  387.   while (LOWER(*s1) == LOWER(*s2) && *s1)
  388.     s1++, s2++;
  389.  
  390.   return LOWER(*s1) - LOWER(*s2);
  391. }
  392.  
  393. int mystrncmp(s1, s2, n)
  394.   char *s1, *s2;
  395.   int n;
  396. {
  397.   while (n && *s1 && *s1 == *s2)
  398.     s1++, s2++, n--;
  399.  
  400.   return n != 0 && *s1 - *s2;
  401. }
  402.  
  403. int mystrnicmp(s1, s2, n)
  404.   char *s1, *s2;
  405.   int n;
  406. {
  407.   while (n && *s1 && LOWER(*s1) == LOWER(*s2))
  408.     s1++, s2++, n--;
  409.  
  410.   return n != 0 && LOWER(*s1) - LOWER(*s2);
  411. }
  412.  
  413. char *myfgets(buf, len, file)
  414.   char *buf;
  415.   int len;
  416.   FILE *file;
  417. {
  418.   char *t, *r;
  419.  
  420.   if ((r = fgets(buf, len, file))) {
  421.     for (t = buf; *t && *t != '\n'; t++);
  422.  
  423.     *t = 0;
  424.   }
  425.   return r;
  426. }
  427.  
  428. char *mystristr(str1, str2)
  429.   char *str1, *str2;
  430. {
  431.   char c = LOWER(*str1), l = strlen(str1);
  432.  
  433.   for (;;) {
  434.     while (*str2 && LOWER(*str2) != c)
  435.       str2++;
  436.  
  437.     if (!*str2)
  438.       break;
  439.  
  440.     if (!mystrnicmp(str1, str2, l))
  441.       return str2;
  442.  
  443.     str2++;
  444.   }
  445.  
  446.   return 0;
  447. }
  448.  
  449. long myatoi(s)
  450.   char *s;
  451. {
  452.   long r = 0;
  453.  
  454.   while (*s && *s >= '0' && *s <= '9')
  455.     r = 10 * r + *s++ - '0';
  456.  
  457.   return r;
  458. }
  459.  
  460. char rdmbuf[200];
  461.  
  462. char *
  463. get_readme(e)
  464.   ENTRY *e;
  465. {
  466.   mystrcpy(rdmbuf,e->file);
  467.   mystrcpy(rdmbuf+strlen(rdmbuf)-e->readmelen, ".readme");
  468.   return rdmbuf;
  469. }
  470.  
  471. #define MYMIN(x,y) ((x)<(y) ? (x) : (y))
  472. #define MYMAX(x,y) ((x)>(y) ? (x) : (y))
  473.  
  474.  
  475. #ifdef AMIGA
  476.  
  477. char *glob_path (buf)
  478.   char *buf;
  479. {
  480.   return buf;
  481. }
  482.  
  483. #else
  484.  
  485. #include <pwd.h>
  486.  
  487. char *glob_path (buf)
  488.   char *buf;
  489. {
  490.   short bindex = 1;
  491.   struct passwd pw_info, *pw;
  492.   char buf2[300];
  493.  
  494.   if (buf[0] != '~')
  495.     return buf;
  496.  
  497.   pw_info.pw_dir = (char *) getenv("HOME");
  498.   if (buf[1] && buf[1] != '/') {
  499.     char username[128];
  500.  
  501.     while (buf[bindex] && buf[bindex] != '/')
  502.         ++bindex;
  503.     memcpy( username, buf+1, bindex-1);
  504.     username[bindex-1] = 0;
  505.  
  506.     if (pw = getpwnam(username))
  507.       pw_info.pw_dir = pw->pw_dir;
  508.     else
  509.       pw_info.pw_dir = "~";
  510.   }
  511.  
  512.   mystrcpy (buf2, pw_info.pw_dir);
  513.   strcat (buf2, buf + bindex);
  514.   mystrcpy (buf, buf2);
  515.  
  516.   return buf;
  517. }
  518. #endif
  519.  
  520.  
  521. /*-----------------------------options and settings--------------------------*/
  522. char *Options[] = {
  523.   "method", "ftp",
  524.   "fspsite", "ftp.wustl.edu,21",
  525.   "fspsites", "ftp.wustl.edu,21",
  526.   "mailserv", "ftp.doc.ic.ac.uk",
  527.   "timeout", "30",
  528.   "nomotd", "0",
  529.   "amotd", "0",
  530.   "lmotd", "0",
  531.   "sites", "0",
  532.   "locaminet", "",
  533.   "unpack", "",
  534.   "transfer", "",
  535.   "newest", "0",
  536.   "hide", "",
  537.   "printer", "",
  538.   "dlpath", "",
  539.   "compress", "1",
  540.   "send", "sz",
  541.   "silentdl", "0",
  542.   "readmedl", "0",
  543.   "flatdl", "1",
  544.   "ftpsite", "ftp.eunet.ch",
  545.   "ftpmaster", "ftp.cdrom.com",
  546.   "ftpsites", "USA (MO),ftp.wustl.edu,128.252.135.4,,@\
  547. USA (WI),ftp.netnet.net,198.70.64.21,,@\
  548. USA (AZ),ftp.amigalib.com,165.247.33.6,,@\
  549. Australia,ftp.livewire.com.au,203.16.26.3,,@\
  550. Scandinavia,ftp.luth.se,130.240.16.39,,@\
  551. Switzerland,ftp.eunet.ch,146.228.10.11,,@\
  552. Germany,ftp.germany.aminet.org,131.234.10.42,,@\
  553. Germany,kelly.uni-paderborn.de,131.234.128.206,,@\
  554. Germany,ftp.uni-stuttgart.de,129.96.18.15,aminet,kelly.uni-paderborn.de@\
  555. Germany,ftp.uni-erlangen.de,131.188.3.2,,kelly.uni-paderborn.de@\
  556. Germany,ftp.cs.tu-berlin.de,130.149.18.7,,kelly.uni-paderborn.de@\
  557. Germany,ftp.tu-chemnitz.de,134.109.132.28,,kelly.uni-paderborn.de@\
  558. Germany,ftp.fh-augsburg.de,141.82.16.242,,kelly.uni-paderborn.de@\
  559. Germany,ftp.uni-bremen.de,134.102.228.2,,kelly.uni-paderborn.de@\
  560. Germany,ftp.uni-kl.de,131.246.94.94,,kelly.uni-paderborn.de@\
  561. Germany,ftp.uni-trier.de,136.199.8.81,,kelly.uni-paderborn.de@\
  562. Germany,ftp.informatik.rwth-aachen.de,137.226.225.3,,kelly.uni-paderborn.de@\
  563. Germany,ftp.uni-siegen.de,141.99.164.1,,kelly.uni-paderborn.de@\
  564. Germany,ftp.uni-regensburg.de,132.199.1.203,,kelly.uni-paderborn.de@\
  565. France,sunsite.cnam.fr,163.173.129.5,,kelly.uni-paderborn.de@\
  566. France,aminet.grolier.fr,194.51.174.67,,kelly.uni-paderborn.de@\
  567. Austria,ftp.giga.or.at,131.130.12.58,,ftp.eunet.ch@\
  568. Italy,ftp.unina.it,192.132.34.17,,@\
  569. Portugal,ftp.ua.pt,193.136.80.68,,kelly.uni-paderborn.de@\
  570. Spain,ftp.gui.uva.es,157.88.36.190,,kelly.uni-paderborn.de@\
  571. UK,ftp.doc.ic.ac.uk,146.169.17.5,,@\
  572. UK,micros.hensa.ac.uk,194.80.32.51,,ftp.doc.ic.ac.uk
  573. ",
  574.   "findmethod", "",
  575.   "findsite", "",
  576.   "findsites", "USA (MO),ftp.wustl.edu,128.252.135.4,,@\
  577. Switzerland,amiga.icu.net.ch,146.228.204.2,,@\
  578. Germany,find.germany.aminet.org,131.234.38.2,,@\
  579. Portugal,ftp.ua.pt,193.136.80.68,,@\
  580. Australia,ftp.livewire.com.au,203.16.26.3,,
  581. ",
  582.   0, 0
  583. };
  584.  
  585. #define OBUFLEN 2000
  586. char obuf[OBUFLEN];
  587.  
  588. char *option_get(name)
  589.   char *name;
  590. {
  591.   char **t;
  592.  
  593.   for (t = Options; t[0]; t += 2)
  594.     if (!mystrcmp(name, t[0]))
  595.       return t[1];
  596.  
  597.   return "";
  598. }
  599.  
  600. int option_getnum(name)
  601.   char *name;
  602. {
  603.   return myatoi(option_get(name));
  604. }
  605.  
  606. int option_set(name, val)
  607.   char *name, *val;
  608. {
  609.   char **t;
  610.  
  611.   for (t = Options; t[0]; t += 2)
  612.     if (!mystrcmp(name, t[0]))
  613.       mystrcpy((t[1] = salloc(strlen(val) + 1)), val);
  614.  
  615.   return 0;
  616. }
  617.  
  618. int option_setnum(name, val)
  619.   char *name;
  620.   int val;
  621. {
  622.   char buf[20];
  623.  
  624.   sprintf(buf, "%d", val);
  625.   option_set(name, buf);
  626.  
  627.   return 0;
  628. }
  629.  
  630. int option_loadfh(f)
  631.   FILE *f;
  632. {
  633.   char *t;
  634.  
  635.   fgets(obuf, OBUFLEN, f);
  636.   if (mystrncmp("#adtrc-v2", obuf, 9))
  637.     return 1;
  638.  
  639.   while (myfgets(obuf, OBUFLEN, f)) {
  640.     while (*obuf && obuf[strlen(obuf)-1]=='\\' && 
  641.            myfgets(obuf+strlen(obuf)-1, OBUFLEN-strlen(obuf)-1, f)) ;
  642.       
  643.     for (t = obuf; *t && *t != '='; t++);
  644.  
  645.     if (*t == '=') {
  646.       *t++ = 0;
  647.       option_set(obuf, t);
  648.     }
  649.   }
  650.  
  651.   return 0;
  652. }
  653.  
  654. int option_load(name)
  655.   char *name;
  656. {
  657.   FILE *f;
  658.   int r;
  659.  
  660.   if (!(f = fopen(name, "r")))
  661.     return 1;
  662.  
  663.   r = option_loadfh(f);
  664.  
  665.   fclose(f);
  666.  
  667.   return r;
  668. }
  669.  
  670. int option_save(name)
  671.   char *name;
  672. {
  673.   FILE *f;
  674.   char **t;
  675.  
  676.   if (!(f = fopen(name, "w")))
  677.     return 1;
  678.  
  679.   fprintf(f, "#adtrc-v2\n");
  680.  
  681.   for (t = Options; t[0]; t += 2)
  682.     fprintf(f, "%s=%s\n", t[0], t[1]);
  683.  
  684.   fclose(f);
  685.  
  686.   return 0;
  687. }
  688.  
  689. /*-----------------------------input file parser-----------------------------*/
  690. #define PBUFSIZE 400
  691. char parsebuf[PBUFSIZE], p_error, *p_ptr;
  692.  
  693. int reset_token()
  694. {
  695.   p_ptr = parsebuf;
  696.   p_error = 0;
  697.   return 0;
  698. }
  699.  
  700.  
  701. char *get_token()
  702. {
  703.   char *t, *s, *d;
  704.  
  705.   if (!p_ptr) {
  706.     p_error = 1;
  707.     return "";
  708.   }
  709.   for (t = s = d = p_ptr; *s && *s != '@'; s++) {
  710.     if (*s != '\r')
  711.       *d++ = *s;
  712.   }
  713.  
  714.   if (!*s)
  715.     p_ptr = 0;
  716.   else {
  717.     *s = 0;
  718.     p_ptr = s + 1;
  719.   }
  720.  
  721.   return t;
  722. }
  723.  
  724.  
  725. long p_atoi(s)
  726.   char *s;
  727. {
  728.   long r = 0;
  729.  
  730.   while (*s && *s >= '0' && *s <= '9')
  731.     r = 10 * r + *s++ - '0';
  732.  
  733.   if (*s)
  734.     p_error = 1;
  735.  
  736.   return r;
  737. }
  738.  
  739.  
  740. int read_adt_v2(fh)
  741.   FILE *fh;
  742. {
  743.   ENTRY *e;
  744.   char *t;
  745.  
  746.   do {
  747.     if (*parsebuf == '#')
  748.       if (!mystrncmp(parsebuf, "#endadt", 7))
  749.     break;
  750.       else
  751.     continue;
  752.  
  753.     e = e_alloc();
  754.  
  755.     reset_token();
  756.  
  757.     e->time = p_atoi(get_token());
  758.  
  759.     mystrncpy(e->dir, get_token(), E_DIR);
  760.  
  761.     mystrncpy(e->file, get_token(), E_FILE);
  762.  
  763.     e->size = p_atoi(get_token());
  764.  
  765.     e->readmelen = p_atoi(get_token());
  766.  
  767.     e->readmesize = p_atoi(get_token());
  768.  
  769.     e->version = -1;
  770.  
  771.     e->osversion = -1;
  772.  
  773.     e->status = *get_token()=='R' ? STATUS_REMOTE : STATUS_LOCAL;
  774.  
  775.     mystrncpy(e->desc, get_token(), E_DESC);
  776.  
  777.     for (t = e->desc; *t; t++)
  778.       if (*t == '\n')
  779.     *t = 0;
  780.  
  781.     e->tagged = 0;
  782.  
  783.     if (!(p_error))
  784.       e_add(File, e);
  785.   } while (fgets(parsebuf, PBUFSIZE, fh));
  786.  
  787.   return 0;
  788. }
  789.  
  790. /*----------------------------------utility----------------------------------*/
  791. long newesttime()
  792. {
  793.   int i;
  794.   long newest = 0;
  795.  
  796.   for (i = 0; i < File->num; i++)
  797.     if ((File->list[i]->time < time(NULL)) && (File->list[i]->time > newest))
  798.       newest = File->list[i]->time;
  799.  
  800.   return newest;
  801. }
  802.  
  803. char *temp_name(buf, sub)
  804.   char *buf;
  805.   char *sub;
  806. {
  807.   sprintf(buf, "%s%s_%s", TEMPPATH, UserName, sub);
  808.   return buf;
  809. }
  810.  
  811. struct temp_file {
  812.   FILE *fh;
  813.   char name[100];
  814.   int (*cleanup) ();
  815. };
  816. #define TEMPFILE struct temp_file
  817.  
  818. int temp_delete(tfh)
  819.   TEMPFILE *tfh;
  820. {
  821.   if (*tfh->name)
  822.     unlink(tfh->name);
  823.   return 0;
  824. }
  825.  
  826. int temp_dummy()
  827. {
  828.   return 0;
  829. }
  830.  
  831. char tclose(tfh)
  832.   TEMPFILE *tfh;
  833. {
  834.   fclose(tfh->fh);
  835.   if (tfh->cleanup)
  836.     (*tfh->cleanup) (tfh);
  837.   return 0;
  838. }
  839.  
  840. int exists(name)
  841.   char *name;
  842. {
  843.   FILE *f;
  844.  
  845.   if ((f = fopen(name, "r")))
  846.     fclose(f);
  847.   return f != 0;
  848. }
  849.  
  850. char *tackon(buf, add)
  851.   char *buf, *add;
  852. {
  853.   if (*buf && (buf[strlen(buf) - 1] != '/' && buf[strlen(buf) - 1] != ':'))
  854.     strcat(buf, "/");
  855.   strcat(buf, add);
  856.  
  857.   return buf;
  858. }
  859.  
  860. char *basename(s)
  861.   char *s;
  862. {
  863.   char *b = s;
  864.  
  865.   for (; *s; s++)
  866.     if (*s == '/' || *s == ':')
  867.       b = s + 1;
  868.  
  869.   return b;
  870. }
  871.  
  872.  
  873. #define NUMLINES 500
  874. char *Lines[NUMLINES + 1];
  875. char LineBuf[200];
  876.  
  877. char **read_file(f, title)
  878.   FILE *f;
  879.   char *title;
  880. {
  881.   int i=0;
  882.   char *t;
  883.  
  884.   if (title) {
  885.     Lines[i]= (char *) salloc( mystrlen(title) + 1 );
  886.     mystrcpy (Lines[i++], title);
  887.   }
  888.  
  889.   for ( ; i < NUMLINES; i++) {
  890.     if (!(fgets(LineBuf, 200, f)))
  891.       break;
  892.     for (t = LineBuf; *t && *t != '\n'; t++);
  893.     *t = 0;
  894.     Lines[i] = (char *) salloc(mystrlen(LineBuf) + 1);
  895.     mystrcpy(Lines[i], LineBuf);
  896.   }
  897.   Lines[i] = 0;
  898.   return Lines;
  899. }
  900.  
  901. int free_file(strings)
  902.   char **strings;
  903. {
  904.   while (*strings)
  905.     free(*strings++);
  906.   return 0;
  907. }
  908.  
  909. /*-----------------------------------sorting---------------------------------*/
  910.  
  911. int cmp_age(e1, e2)
  912.   ENTRY *e1, *e2;
  913. {
  914.   return e2->time - e1->time;
  915. }
  916.  
  917. int cmp_dir(e1, e2)
  918.   ENTRY *e1, *e2;
  919. {
  920.   int t;
  921.  
  922.   return (t = mystricmp(e1->dir, e2->dir)) ? t : mystricmp(e1->file, e2->file);
  923. }
  924.  
  925. int cmp_size(e1, e2)
  926.   ENTRY *e1, *e2;
  927. {
  928.   return e2->size - e1->size;
  929. }
  930.  
  931. int cmp_name(e1, e2)
  932.   ENTRY *e1, *e2;
  933. {
  934.   return mystricmp(e1->file, e2->file);
  935. }
  936.  
  937. int cmp_rage(e2, e1)
  938.   ENTRY *e1, *e2;
  939. {
  940.   return e2->time - e1->time;
  941. }
  942.  
  943. int cmp_rdir(e2, e1)
  944.   ENTRY *e1, *e2;
  945. {
  946.   int t;
  947.  
  948.   return (t = mystricmp(e1->dir, e2->dir)) ? t : mystricmp(e1->file, e2->file);
  949. }
  950.  
  951. int cmp_rsize(e2, e1)
  952.   ENTRY *e1, *e2;
  953. {
  954.   return e2->size - e1->size;
  955. }
  956.  
  957. int cmp_rname(e2, e1)
  958.   ENTRY *e1, *e2;
  959. {
  960.   return mystricmp(e1->file, e2->file);
  961. }
  962.  
  963. struct sort_mode {
  964.   int (*cmp) ();
  965.   char *desc;
  966. };
  967. #define SORT struct sort_mode
  968.  
  969. SORT
  970. sort_age   = { cmp_age,   "par date (le plus jeune en premier)" },
  971. sort_dir   = { cmp_dir,   "par répertoire" },
  972. sort_size  = { cmp_size,  "par taille" },
  973. sort_name  = { cmp_name,  "par nom" },
  974. sort_rage  = { cmp_rage,  "par date (le plus vieux en premier)" },
  975. sort_rdir  = { cmp_rdir,  "par répertoire (inverse)" },
  976. sort_rsize = { cmp_rsize, "par taille (inverse)" },
  977. sort_rname = { cmp_rname, "par nom (inverse)" };
  978.  
  979. int quick_sort(av, n, cmp)
  980.   ENTRY **av;
  981.   int n, (*cmp) ();
  982. {
  983.   ENTRY **i, **j, *x, *t;
  984.  
  985.   if (n > 0) {
  986.     i = av;
  987.     j = av + n - 1;
  988.     x = av[n >> 1];
  989.     do {
  990.       while (cmp(*i, x) < 0)
  991.     i++;
  992.       while (cmp(x, *j) < 0)
  993.     --j;
  994.       if (i <= j)
  995.     t = *i, *i = *j, *j = t, i++, j--;
  996.  
  997.     } while (i <= j);
  998.  
  999.     if (j + 1 - av < av + n - i) {
  1000.       quick_sort(av, j + 1 - av, cmp);
  1001.       quick_sort(i, av + n - i, cmp);
  1002.     } else {
  1003.       quick_sort(i, av + n - i, cmp);
  1004.       quick_sort(av, j + 1 - av, cmp);
  1005.     }
  1006.   }
  1007.   return 0;
  1008. }
  1009.  
  1010. int sort_list(list, sort)
  1011.   LIST *list;
  1012.   SORT *sort;
  1013. {
  1014.  
  1015.   quick_sort(list->list, list->num, sort->cmp);
  1016.  
  1017.   list->current = list->offset = 0;
  1018.  
  1019.   Vis->sort = sort->desc;
  1020.  
  1021.   return 0;
  1022. }
  1023.  
  1024.  
  1025. /*---------------------------------visibility--------------------------------*/
  1026.  
  1027. int allvisible()
  1028. {
  1029.   int i;
  1030.  
  1031.   l_store();
  1032.   l_reset(Vis);
  1033.  
  1034.   Vis->sel = "Tous les fichiers";
  1035.   for (i = 0; i < File->num; i++)
  1036.     e_add(Vis, File->list[i]);
  1037.  
  1038.   sort_list(Vis, &sort_dir);
  1039.  
  1040.   return 0;
  1041. }
  1042.  
  1043. int invisible()
  1044. {
  1045.   ENTRY **entr = Vis->list;
  1046.   char buf[200], *b, *h = option_get("hide");
  1047.   int i, j;
  1048.  
  1049.   while (*h) {
  1050.     b = buf;
  1051.     while (*h && *h != ' ' && *h != ',')
  1052.       *b++ = *h++;
  1053.     *b = 0;
  1054.  
  1055.     while (*h && (*h == ' ' || *h == ','))
  1056.       h++;
  1057.  
  1058.     if (!*buf)
  1059.       continue;
  1060.  
  1061.     for (i = j = 0; i < Vis->num; i++)
  1062.       if (mystrncmp(buf, entr[i]->dir, b - buf))
  1063.     entr[j++] = entr[i];
  1064.     Vis->num = j;
  1065.   }
  1066.   Vis->current = 0;
  1067.  
  1068.   return 0;
  1069. }
  1070.  
  1071. int newvisible()
  1072. {
  1073.   ENTRY **entr = File->list;
  1074.   int i;
  1075.  
  1076.   l_store();
  1077.   l_reset(Vis);
  1078.   Vis->sel = "Nouveaux fichiers";
  1079.  
  1080.   for (i = 0; i < File->num; i++)
  1081.     if (entr[i]->time > LastCall)
  1082.       e_add(Vis, entr[i]);
  1083.  
  1084.   invisible();
  1085.  
  1086.   if (!Vis->num && File->num)
  1087.     NoFilesString = "Pas de nouveau fichier, v)oir k)onnu pour consulter les anciens";
  1088.  
  1089.   sort_list(Vis, &sort_dir);
  1090.  
  1091.   return 0;
  1092. }
  1093.  
  1094. int dirvisible(dir)
  1095.   char *dir;
  1096. {
  1097.   ENTRY **entr = File->list;
  1098.   int i, l = strlen(dir);
  1099.  
  1100.   l_store();
  1101.   l_reset(Vis);
  1102.   Vis->sel = "Répertoire sélectionné";
  1103.  
  1104.   for (i = 0; i < File->num; i++)
  1105.     if (!mystrncmp(entr[i]->dir, dir, l))
  1106.       e_add(Vis, entr[i]);
  1107.  
  1108.   if (!Vis->num && File->num)
  1109.     NoFilesString = "Pas de fichiers correspondant à cette demande";
  1110.  
  1111.   sort_list(Vis, &sort_dir);
  1112.  
  1113.   return 0;
  1114. }
  1115.  
  1116. int findstr(str)
  1117.   char *str;
  1118. {
  1119.   ENTRY **entr = File->list;
  1120.   int i;
  1121.  
  1122.   if (!*str)
  1123.     return 0;
  1124.  
  1125.   l_store();
  1126.   l_reset(Vis);
  1127.  
  1128.   for (i = 0; i < File->num; i++)
  1129.     if (mystristr(str, entr[i]->desc) || mystristr(str, entr[i]->file))
  1130.       e_add(Vis, entr[i]);
  1131.  
  1132.   Vis->sel = "Recherche en cours...";
  1133.  
  1134.   sort_list(Vis, &sort_dir);
  1135.  
  1136.   if (!Vis->num && File->num)
  1137.     NoFilesString = "Pas de fichier correspondant à la demande: usez encore de f)ouiner";
  1138.  
  1139.   return 0;
  1140. }
  1141.  
  1142.  
  1143. int strlimit(str)
  1144.   char *str;
  1145. {
  1146.   ENTRY **entr = Vis->list;
  1147.   int i, j;
  1148.  
  1149.   if (!*str)
  1150.     return 0;
  1151.  
  1152.   l_store();
  1153.   Vis->sel = "Recherche en cours...";
  1154.  
  1155.   for (i = j = 0; i < Vis->num; i++)
  1156.     if (mystristr(str, entr[i]->desc) || mystristr(str, entr[i]->file))
  1157.       entr[j++] = entr[i];
  1158.  
  1159.   Vis->num = j;
  1160.   Vis->current = 0;
  1161.  
  1162.   if (!Vis->num && File->num)
  1163.     NoFilesString = "Pas de fichier correspondant, v)oir pour encore en voir";
  1164.  
  1165.   return 0;
  1166. }
  1167.  
  1168. int togglevisible()
  1169. {
  1170.   LIST *l;
  1171.  
  1172.   l = Vis;
  1173.   Vis = Alt;
  1174.   Alt = l;
  1175.   return 0;
  1176. }
  1177.  
  1178.  
  1179. int markedvisible()
  1180. {
  1181.   ENTRY **entr;
  1182.   int i, j=0;
  1183.  
  1184.   l_store();
  1185.   Vis->sel = "Fichiers marqués";
  1186.  
  1187.   entr = Vis->list;
  1188.   for (i = 0; i < Vis->num; i++)
  1189.     if (entr[i]->tagged)
  1190.       entr[j++]=entr[i];
  1191.  
  1192.   if (!(Vis->num=j) && File->num)
  1193.     NoFilesString = "Pas de fichier marqué";
  1194.  
  1195.   return 0;
  1196. }
  1197.  
  1198. int markedextract()
  1199. {
  1200.   ENTRY **entr = Vis->list;
  1201.   int i;
  1202.  
  1203.   l_reset(Mark);
  1204.  
  1205.   for (i = 0; i < Vis->num; i++)
  1206.     if (entr[i]->tagged)
  1207.       e_add(Mark, entr[i]);
  1208.  
  1209.   if (!Mark->num)
  1210.     e_add(Mark, entr[Vis->current]);
  1211.  
  1212.   return 0;
  1213. }
  1214.  
  1215.  
  1216.  
  1217. /*-----------------------------string formatting-----------------------------*/
  1218. char *ShowFiles = "Nouveaux fichiers par répertoire";
  1219. int CurSelected, Window;
  1220.  
  1221. char *str_topline(buf, len, list)
  1222.   LIST *list;
  1223.   int len;
  1224.   char *buf;
  1225. {
  1226.   int i;
  1227.   char buf2[40];
  1228.  
  1229.   for (i = 0; i < len; i++)
  1230.     buf[i] = ' ';
  1231.   buf[i] = 0;
  1232.  
  1233.   sprintf(buf2, "Affichage: %d/%d", list->num, File->num);
  1234.   mystrcpy(buf, buf2);
  1235.   buf[strlen(buf)] = ' ';
  1236.  
  1237.   sprintf(buf2, "%s %s", Vis->sel, Vis->sort);
  1238.   mystrcpy(buf + len / 2 - strlen(buf2) / 2, buf2);
  1239.   buf[strlen(buf)] = ' ';
  1240.  
  1241.   sprintf(buf2, "Page: %d/%d", 1 + list->offset / Window, 1 + list->num / Window);
  1242.   mystrcpy(buf + len - strlen(buf2), buf2);
  1243.  
  1244.   return buf;
  1245. }
  1246.  
  1247.  
  1248. char sizestr[10];
  1249.  
  1250. char *str_ksize(size)
  1251.   long size;
  1252. {
  1253.   if (size == -1) {
  1254.     sprintf(sizestr, "?");
  1255.   } else {
  1256.     size = (size + 512) / 1024;
  1257.     if (size <= 999)
  1258.       sprintf(sizestr, "%dK  ", size);
  1259.     else if ((size + 512) / 1024 < 10)
  1260.       sprintf(sizestr, "%d.%d  M", (size + 512) / 1024, (size * 10 + 512) / 1024 % 10);
  1261.     else
  1262.       sprintf(sizestr, "%dM  ", (size + 512) / 1024);
  1263.   }
  1264.   return sizestr;
  1265. }
  1266.  
  1267.  
  1268. char *str_titles(buf)
  1269.   char *buf;
  1270. {
  1271.   switch (Dispmode) {
  1272.   case 0:
  1273.     mystrcpy(buf, " Fichier              Rep.       Taille Description\n");
  1274.     break;
  1275.   }
  1276.   return buf;
  1277. }
  1278.  
  1279.  
  1280.  
  1281. char *str_entry(e, n, max, buf, len)
  1282.   ENTRY **e;
  1283.   int n, max, len;
  1284.   char *buf;
  1285. {
  1286.   int i;
  1287.  
  1288.   if (n >= max) {
  1289.     for (i = 0; i < len; i++)
  1290.       buf[i] = ' ';
  1291.     buf[i] = 0;
  1292.     return buf;
  1293.   }
  1294.   switch (Dispmode) {
  1295.   case 0:
  1296.     sprintf(buf, "%c%-20.20s %-10.10s %6.6s%c%-80.80s",
  1297.         e[n]->tagged ? '+' : ' ',
  1298.         e[n]->file,
  1299.         e[n]->dir,
  1300.         str_ksize(e[n]->size),
  1301.         e[n]->readmesize > 100 ? '+' : ' ',
  1302.         e[n]->desc);
  1303.     buf[len - 1] = 0;
  1304.     break;
  1305.   }
  1306.  
  1307.  
  1308.   return buf;
  1309. }
  1310.  
  1311.  
  1312. char sitebuf[120];
  1313.  
  1314. int str_sitesplit(s, parts)
  1315.   char *s, **parts;
  1316. {
  1317.   char *d = sitebuf;
  1318.   int i;
  1319.  
  1320.   for (i = 0; i < 5; i++) {
  1321.     parts[i] = d;
  1322.     while (*s && *s != ',' && *s != '@')
  1323.       *d++ = *s++;
  1324.     if (*s == ',')
  1325.       s++;
  1326.     *d++ = 0;
  1327.   }
  1328.  
  1329.   return 0;
  1330. }
  1331.  
  1332. char *str_showline(entries, n, max, buf)
  1333.   char *entries, *buf;
  1334.   int n, max;
  1335. {
  1336.   char *s = entries;
  1337.   char *parts[10];
  1338.  
  1339.   if (n >= max)
  1340.     return "";
  1341.  
  1342.   for (; n > 0; n--)
  1343.     while (*s++ != '@');
  1344.  
  1345.   str_sitesplit(s, parts);
  1346.   sprintf(buf, "%-12.12s %24.24s", parts[0], parts[1]);
  1347.  
  1348.   return buf;
  1349. }
  1350.  
  1351. char centerbuf[1024];
  1352.  
  1353. char *str_center(s, len)
  1354.   char *s;
  1355.   int len;
  1356. {
  1357.   int i = (len - strlen(s)) / 2 - 1;
  1358.   strcpy(centerbuf + i, s); 
  1359.   while (i > 0)
  1360.     centerbuf[--i] = ' ';
  1361.  
  1362.   return centerbuf;
  1363. }
  1364.  
  1365.  
  1366. int str_longest(arr)
  1367.   char **arr;
  1368. {
  1369.   int l = 0;
  1370.  
  1371.   for (; *arr; arr++)
  1372.     if (strlen(*arr) > l)
  1373.       l = strlen(*arr);
  1374.   return l;
  1375. }
  1376.  
  1377. int str_shift(len, width)
  1378.   int len, width;
  1379. {
  1380.   return len < width ? (width - len) / 2 : 0;
  1381. }
  1382.  
  1383. LIST sitelist = {0, str_showline, 0, 0, 0, 0, 1, 0};
  1384.  
  1385. int setup_sitelist(sitesname, sitename, help)
  1386.   char *sitesname, *sitename, **help;
  1387. {
  1388.   int t, n = 1;
  1389.   char *sites = option_get(sitesname), *s;
  1390.   char buf[100], *d = buf;
  1391.  
  1392.   mystrcpy(buf, option_get("ftpsite"));
  1393.  
  1394.   for (s = sites; *s; ) {
  1395.     if (*s++ == '@') {
  1396.       if (*buf && !mystrncmp(s, buf, strlen(buf)))
  1397.     sitelist.current = n;
  1398.       n++;
  1399.     }
  1400.   }
  1401.  
  1402.   sitelist.list = (ENTRY **) sites;
  1403.   sitelist.num = n;
  1404.  
  1405.   if ((t = disp_choice(help, &sitelist)) < 0)
  1406.     return 1;
  1407.  
  1408.   for (s = sites; t > 0; t--)
  1409.     while (*s++ != '@');
  1410.  
  1411.   while (*s && *s != '@')
  1412.     *d++ = *s++;
  1413.   *d++ = 0;
  1414.  
  1415.   option_set(sitename, buf);
  1416.  
  1417.   return 0;
  1418. }
  1419.  
  1420. /*-----------------------------command key input-----------------------------*/
  1421. #define K_UP     300
  1422. #define K_DOWN   301
  1423. #define K_RIGHT  302
  1424. #define K_LEFT   303
  1425.  
  1426. int inp_getchr()
  1427. {
  1428.   int c;
  1429.  
  1430.   if ((c = disp_getchar()) != 27 && c != 155)
  1431.     return c;
  1432.  
  1433.   if (c == 27 && (c = disp_getchar()) != '[')
  1434.     return c;
  1435.  
  1436.   switch (c = disp_getchar()) {
  1437.   case 'A':
  1438.     return K_UP;
  1439.   case 'B':
  1440.     return K_DOWN;
  1441.   case 'C':
  1442.     return K_RIGHT;
  1443.   case 'D':
  1444.     return K_LEFT;
  1445.   }
  1446.   return 0;
  1447. }
  1448.  
  1449. /*-------------------------------initial setup-------------------------------*/
  1450. char *setup_showline(entries, n, max)
  1451.   TRANSFER entries[];
  1452.   int n, max;
  1453. {
  1454.   return n < max ? entries[n].text : "";
  1455. }
  1456.  
  1457. LIST setuplist = {(ENTRY **) TransferTypes, setup_showline, 0, 0, 0, 0, 1, 0};
  1458.  
  1459. char *FirstSetupHelp[] = {
  1460.   "ADT Configuration initiale",
  1461.   "Je crois que c'est ta premiere session ADT. ADT accède à des fichiers"
  1462.   "sauvés sur un serveur Aminet à l'aide de diverses méthodes (FTP,FSP",
  1463.   "mail, serveurs). La version que vous possédez ne les supporte pas tous",  
  1464.   "Selectionnez votre méthode de tranfert maintenant!!",
  1465.   "NOTE: Après la configuration, vous pouvez taper 'h' ou '?' pour l'aide",
  1466.   "à n'importe quel endroit.",0  
  1467. };
  1468.  
  1469. char *SetupHelp[] = {
  1470.   "ADT: configuration de la méthode de transfert",
  1471.   "Sélectionnez la méthode que doit utiliser ADT pour le transfert", 0
  1472. };
  1473.  
  1474. int setup_method()
  1475. {
  1476.   TRANSFER *type;
  1477.   int n;
  1478.  
  1479.   setuplist.current = 0;
  1480.   setuplist.num = 0;
  1481.   for (type = TransferTypes; type->text; type++) {
  1482.     if (!mystrcmp(type->name, option_get("method")))
  1483.       setuplist.current = setuplist.num;
  1484.     setuplist.num++;
  1485.   }
  1486.  
  1487.   n = disp_choice(InitialSetup ? FirstSetupHelp : SetupHelp, &setuplist);
  1488.  
  1489.   if (n < 0) {
  1490.     if (InitialSetup)
  1491.       exit_adt("Je ne peux pas démarrer sans savoir le type de transfert. Salut.");
  1492.   } else {
  1493.     if (trans_close)
  1494.       trans_close();
  1495.     option_set("method", TransferTypes[n].name);
  1496.     TransferTypes[n].init();
  1497.     trans_options();
  1498.   }
  1499.  
  1500.   return 0;
  1501. }
  1502.  
  1503.  
  1504. char *DefaultsHelp[] = {
  1505.   "ADT Configuration initiale",
  1506.   "Je crois que c'est votre première utilisation d'ADT. Il permet d'avoir",
  1507.   "accès à des bases de fichiers à l'aide de différents services (FTP,",
  1508.   "FSP, serveur de mail etc...). Votre administrateur système à déjà",
  1509.   "sélectionné un service par défaut ainsi qu'un site. Ils vont être",
  1510.   "sauvés dans votre configuration locale lorsque vous q)uitterez ADT",
  1511.   "Vous pourrez le modifiez à loisir avec les o)ptions.",
  1512.   "Appuyez sur une touche pour utiliser ADT",0
  1513. };
  1514.  
  1515. int setup_defaults()
  1516. {
  1517.   option_set("newest", "0");
  1518.  
  1519.   return 0;
  1520. }
  1521.  
  1522.  
  1523.  
  1524. char *enum_showline(entries, n, max, buf)
  1525.   char **entries, *buf;
  1526.   int n, max;
  1527. {
  1528.   if (n >= max)
  1529.     return "";
  1530.   else
  1531.     return entries[n];
  1532. }
  1533.  
  1534.  
  1535. LIST enumlist = {0, enum_showline, 0, 0, 0, 0, 1, 0};
  1536.  
  1537. int setup_enumed(help, choices, var)
  1538.   char **help, **choices, *var;
  1539. {
  1540.   int n, lines, t;
  1541.  
  1542.   for (lines = 0; choices[lines]; lines++);
  1543.  
  1544.   n = option_getnum(var);
  1545.   if (n < 0)
  1546.     n = 0;
  1547.   if (n >= lines)
  1548.     n = lines - 1;
  1549.  
  1550.   enumlist.list = (ENTRY **) choices;
  1551.   enumlist.num = lines;
  1552.   enumlist.current = n;
  1553.  
  1554.   t = disp_choice(help, &enumlist);
  1555.  
  1556.   if (t >= 0)
  1557.     option_setnum(var, t);
  1558.  
  1559.   return t;
  1560. }
  1561.  
  1562.  
  1563. char *FindMethodHelp[] = {
  1564.   "Méthode de recherche",
  1565.   "Sélectionner la méthode approprié pour trouver des fichiers Aminet",
  1566.   "Vous pouvez utiliser un serveur à-la Archie si vous avez un accès",
  1567.   "Internet. Sinon, vous pouvez faire plusieurs requètes à la fois",
  1568.   "ou si votre connection est très rapide (fichiers locaux), il est peut",
  1569.   "être mieux pour ADT de ramener l'INDEX complet et de faire les requêtes",
  1570.   "localement. Si vous voulez seulement chercher dans ce qui est disponible",
  1571.   "sur votre site, choisissez la troisième option",0
  1572. }, *FindMethodList[] = {
  1573.   "Recherche sur le serveur lointain sur l'index Aminet complet",
  1574.   "Recherche locale sur le site Aminet courant",
  1575.   "Recherche locale sur l'index Aminet complet", 0
  1576. };
  1577.  
  1578. char *FindSiteHelp[] = {
  1579.   "Selection du serveur de recherche.",
  1580.   "Quel serveur doit être utilisé pour chercher des programmes?",
  1581.   "Tous les serveurs ont un index Aminet complet et peut être consulté",
  1582.   "pour faire des recherches sur n'importe quel site complet.",0
  1583.  
  1584. };
  1585.  
  1586. int setup_findmethod()
  1587. {
  1588.   if (setup_enumed(FindMethodHelp, FindMethodList, "findmethod") == 0)
  1589.     setup_sitelist("findsites", "findsite", FindSiteHelp);
  1590.  
  1591.   option_save(ConfigFile);
  1592.  
  1593.   return 0;
  1594. }
  1595.  
  1596. /* ==============================GENERIC FILE TRANSFER======================== */
  1597. int trans_init()
  1598. {
  1599.   TRANSFER *t = TransferTypes;
  1600.   char *s = option_get("method");
  1601.  
  1602.   while (t->name && mystrcmp(t->name, s))
  1603.     t++;
  1604.  
  1605.   if (!t->name)
  1606.     return 1;
  1607.  
  1608.   t->init();
  1609.  
  1610.   return 0;
  1611. }
  1612.  
  1613.  
  1614. /* ==============================LOCAL FILE PACKAGE=========================== */
  1615. int CdRom;
  1616.  
  1617. int local_connect(progress)
  1618.   int (*progress) ();
  1619. {
  1620.   Connected = 1;
  1621.   return 0;
  1622. }
  1623.  
  1624. int local_remopen(tfh, remote)
  1625.   TEMPFILE *tfh;
  1626.   char *remote;
  1627. {
  1628.   mystrcpy(tfh->name, option_get("locaminet"));
  1629.   tackon(tfh->name, remote);
  1630.  
  1631.   tfh->cleanup = temp_dummy;
  1632.   tfh->fh = fopen(tfh->name, "r");
  1633.  
  1634.   NoFilesString = "Je ne peux accéder au fichier lointain,  o)ptions s)ite pour changer de chemin";
  1635.  
  1636.   return 0;
  1637. }
  1638.  
  1639. int local_download(remote, locdir, size, progress)
  1640.   char *remote, *locdir;
  1641.   long size;
  1642.   int (*progress) ();
  1643. {
  1644.   char buf[150], buf2[100];
  1645.  
  1646.   sprintf(buf, "Copie de %s", remote);
  1647.   progress(buf);
  1648.  
  1649.   mystrcpy(buf2, option_get("locaminet"));
  1650.   tackon(buf2, remote);
  1651.  
  1652.   sprintf(buf, "%s %s %s", COPYCMD, buf2, locdir);
  1653.   system(buf);
  1654.  
  1655.   sprintf(buf, "Copié %s", remote);
  1656.   progress(buf);
  1657.  
  1658.   return 0;
  1659. }
  1660.  
  1661. int local_disconnect()
  1662. {
  1663.   Connected = 0;
  1664.   return 0;
  1665. }
  1666.  
  1667. #ifdef AMIGA
  1668. char *LocAminetHelp[] = {
  1669.   "Utiliser une base de donnée Aminet locale",
  1670.   "Entrez le chemin absolu vers le répertoire Aminet",
  1671.   "Ex: NET:aminet", 0
  1672. };
  1673.  
  1674. char *CdRomHelp[] = {
  1675.   "Utiliser un CD-ROM aminet",
  1676.   "Entrez le chemin absolu vers votre CD-ROM Aminet en incluant",
  1677.   "la fin de chemin \"Aminet\",",
  1678.   "Exemple: CD0:Aminet. (Notez que vous avez besoin au moins d'Aminet CD 2)",0
  1679. };
  1680.  
  1681. #else
  1682.  
  1683. char *LocAminetHelp[] = {
  1684.   "Utiliser une base de donnée Aminet locale",
  1685.   "Entrez le chemin absolu vers le répertoire Aminet",
  1686.   "N'UTILISEZ PAS le caractère ~. exemple: /ftp/pub/aminet.",0
  1687. };
  1688.  
  1689. char *CdRomHelp[] = {
  1690.   "Utiliser un CD-ROM aminet",
  1691.   "Entrez le chemin absolu vers votre CD-ROM Aminet en incluant",
  1692.   "la fin de chemin \"Aminet\",",
  1693.   "Exemple: /cdrom/Aminet. (Notez que vous avez besoin au moins d'Aminet CD 2)",0
  1694. };
  1695.  
  1696. #endif
  1697.  
  1698.  
  1699.  
  1700.  
  1701. int local_options()
  1702. {
  1703.   char buf[100];
  1704.  
  1705.   if (InitialSetup)
  1706.     option_set("findmethod", "1");
  1707.  
  1708.  
  1709.   mystrcpy(buf, option_get("locaminet"));
  1710.   disp_inputstr(buf, CdRom ? CdRomHelp : LocAminetHelp);
  1711.   option_set("locaminet", buf);
  1712.  
  1713.   return 0;
  1714. }
  1715.  
  1716. int local_close()
  1717. {
  1718.   return 0;
  1719. }
  1720.  
  1721.  
  1722. int local_init()
  1723. {
  1724.   trans_options = local_options;
  1725.   trans_connect = local_connect;
  1726.   trans_remopen = local_remopen;
  1727.   trans_download = local_download;
  1728.   trans_disconnect = local_disconnect;
  1729.   trans_close = local_close;
  1730.  
  1731.   if ( !strcmp ( option_get("method"), "cdrom"))
  1732.     CdRom=1;
  1733.  
  1734.   return 0;
  1735. }
  1736.  
  1737. /* ==============================EXTERNAL FTP PACKAGE========================= */
  1738. #ifndef NO_EXTERNAL_FTP
  1739.  
  1740. FILE *xFtp;
  1741.  
  1742. int xftp_connect(progress)
  1743.   int (*progress) ();
  1744. {
  1745.   char *site = option_get("ftpsite");
  1746.   char *parts[10];
  1747.   char buf[100];
  1748.  
  1749.   if (Connected)
  1750.     return 0;
  1751.   Connected = 1;
  1752.  
  1753.   str_sitesplit(site, parts);
  1754.  
  1755.   sprintf(buf, "Connexion à %s", parts[1]);
  1756.   progress(buf);
  1757.  
  1758.   fprintf(xFtp, "open %s\n", parts[1]);
  1759.   fprintf(xFtp, "user ftp -ftp\n");
  1760.   fprintf(xFtp, "cd pub/aminet\n");
  1761.   fprintf(xFtp, "bin\n");
  1762.  
  1763.   return 0;
  1764. }
  1765.  
  1766. #ifdef AMIGA
  1767. #define xftp_filesize(name) 0
  1768. #else
  1769.  
  1770. static long xftp_filesize(name)
  1771.   char *name;
  1772. {
  1773.   struct stat st;
  1774.  
  1775.   return stat(name, &st) ? -1 : st.st_size;
  1776. }
  1777. #endif
  1778.  
  1779. static int xftp_waitfile(local, size, progress, maxwait, pad, name)
  1780.   char *local;
  1781.   long size;
  1782.   int (*progress) (), maxwait;
  1783.   char *pad, *name;
  1784. {
  1785.   int got, prevgot = -1, timeout = 0;
  1786.   char buf[100];
  1787.  
  1788.   sprintf(buf, "Initialise la récupération de %s", size < 0 ? name : local);
  1789.   progress(buf);
  1790.  
  1791.   while ((got = xftp_filesize(local)) < size || size < 0) {
  1792.  
  1793.     if (got != prevgot)
  1794.       timeout = 0;
  1795.  
  1796.     if (timeout > maxwait)
  1797.       return 1;
  1798.  
  1799.     if (++timeout > 10) {
  1800.       sprintf(buf, "Compte à rebours %d sur le fichier %s", maxwait - timeout, local);
  1801.       progress(buf);
  1802.     }
  1803.     prevgot = got;
  1804.     if (got >= 0) {
  1805.       if (size >= 0)
  1806.     sprintf(buf, "Récupère %s, %3dK/%3dK",
  1807.         local, (got + 512) / 1024, (size + 512) / 1024);
  1808.       else
  1809.     sprintf(buf, "Récupère %s, %3dK", name, (got + 512) / 1024);
  1810.  
  1811.       progress(buf);
  1812.     }
  1813.     if (size < 0 && exists(pad))
  1814.       return 0;
  1815.  
  1816.     sleep(1);
  1817.   }
  1818.  
  1819.   return size >= 0 ? got < size : 0;
  1820. }
  1821.  
  1822. int xftp_remopen(tfh, remote, pack, progress)
  1823.   TEMPFILE *tfh;
  1824.   char *remote, *pack;
  1825.   int (*progress) ();
  1826. {
  1827.   char pad[100], buf[100], remname[100];
  1828.  
  1829.   sprintf(remname, "%s%s", remote, pack);
  1830.  
  1831.   temp_name(pad, "PAD");
  1832.   temp_name(tfh->name, "REMOTE");
  1833.   strcat(tfh->name, pack);
  1834.   tfh->cleanup = temp_delete;
  1835.  
  1836.   unlink(pad);
  1837.   unlink(tfh->name);
  1838.  
  1839.   fprintf(xFtp, "get %s %s\n", remname, tfh->name);
  1840.   fprintf(xFtp, "get info/adt/pad %s\n", pad);
  1841.   fflush(xFtp);
  1842.  
  1843.   xftp_waitfile(tfh->name, -1, progress, 30, pad, basename(remname));
  1844.  
  1845.   unlink(pad);
  1846.  
  1847.   if (*pack) {
  1848.     temp_name(tfh->name, "REMOTE");
  1849.     unlink(tfh->name);
  1850.     sprintf(buf, "%s %s", pack[2] ? "gzip -d" : "uncompress", tfh->name);
  1851.     system(buf);
  1852.   }
  1853.   tfh->fh = fopen(tfh->name, "r");
  1854.  
  1855.   return 0;
  1856. }
  1857.  
  1858.  
  1859. int xftp_download(remote, locdir, size, progress)
  1860.   char *remote, *locdir;
  1861.   int size, (*progress) ();
  1862. {
  1863.   char locname[200];
  1864.  
  1865.   mystrcpy(locname, locdir);
  1866.   tackon(locname, basename(remote));
  1867.  
  1868.   fprintf(xFtp, "get %s %s\n", remote, locname);
  1869.   fflush(xFtp);
  1870.  
  1871.   xftp_waitfile(locname, size, progress, 30, 0);
  1872.  
  1873.   return 0;
  1874. }
  1875.  
  1876.  
  1877. int xftp_disconnect()
  1878. {
  1879.   if (!Connected)
  1880.     return 0;
  1881.   Connected = 0;
  1882.  
  1883.   fprintf(xFtp, "close\n");
  1884.   fflush(xFtp);
  1885.   return 0;
  1886. }
  1887.  
  1888. char *XFTPHelp[] = {
  1889.   "Configuration du client FTP externe",
  1890.   "Vous avez besoin d'un site pour en ramener des fichiers. Choisissez",
  1891.   "d'abord qui est près de la où vous êtes, et vous expérimenterez",
  1892.   "plus tard four trouver l'endroit qui vous convient le mieux.",0
  1893.  
  1894. };
  1895.  
  1896.  
  1897. int xftp_options()
  1898. {
  1899.   setup_sitelist("ftpsites", "ftpsite", XFTPHelp);
  1900.  
  1901.   return 0;
  1902. }
  1903.  
  1904. int xftp_close()
  1905. {
  1906.   if (xFtp) {
  1907.     fprintf(xFtp, "bye\n");
  1908.     pclose(xFtp);
  1909.     xFtp = 0;
  1910.     Connected = 0;
  1911.   }
  1912.   return 0;
  1913. }
  1914.  
  1915. int xftp_init()
  1916. {
  1917.   char buf[100];
  1918.  
  1919.   sprintf(buf, "ftp -n");
  1920.  
  1921.   if (!xFtp && !(xFtp = popen(buf, "w")))
  1922.     exit_adt("Could not start 'ftp'");
  1923.  
  1924.   trans_options = xftp_options;
  1925.   trans_connect = xftp_connect;
  1926.   trans_remopen = xftp_remopen;
  1927.   trans_download = xftp_download;
  1928.   trans_disconnect = xftp_disconnect;
  1929.   trans_close = xftp_close;
  1930.  
  1931.   return 0;
  1932. }
  1933.  
  1934. #endif
  1935.  
  1936.  
  1937. /* ==============================TCP functions========================= */
  1938. #ifndef NO_TCP_UTILITY
  1939.  
  1940. /* creates an new tcp socket and connects it to <host> on port <port>. returns
  1941.  * -1 if a failure occured. NOTE: host can either be a hostname or a
  1942.  * dot-notation of the internet adress */
  1943. int tcp_createsocket(host, port)
  1944.   char *host;
  1945.   int port;
  1946. {
  1947.   struct sockaddr_in sin;
  1948.   struct hostent *h;
  1949.   int connected, net = -1;
  1950.  
  1951.   if ((sin.sin_addr.s_addr = inet_addr(host)) == -1) {
  1952.     if (!(h = gethostbyname(host)))
  1953.       return -1;
  1954.     else {
  1955.       sin.sin_family = h->h_addrtype;
  1956.  
  1957. #ifndef NOT43
  1958.       memcpy((caddr_t) & sin.sin_addr, h->h_addr_list[0], h->h_length);
  1959. #else
  1960.       memcpy((caddr_t) & sin.sin_addr, h->h_addr, h->h_length);
  1961. #endif
  1962.     }
  1963.   } else
  1964.     sin.sin_family = AF_INET;
  1965.  
  1966.   sin.sin_port = htons(port);
  1967.  
  1968.   for (connected = 1; connected && (connected < 30); connected++) {
  1969.     if ((net = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  1970.       return -1;
  1971.  
  1972.     if (connect(net, (struct sockaddr *) & sin, sizeof(sin)) >= 0) {
  1973.       connected = 0;
  1974.       break;
  1975.     } else
  1976.       close(net);
  1977.   }
  1978.  
  1979.   if (!connected)
  1980.     return net;
  1981.   else
  1982.     return -1;
  1983. }
  1984.  
  1985. #endif
  1986.  
  1987. /* ==============================BUILTIN FTP PACKAGE========================= */
  1988. #ifndef NO_BUILTIN_FTP
  1989.  
  1990. #ifndef BFTP_BUFSIZE
  1991. # define BFTP_BUFSIZE 10000
  1992. #endif
  1993.  
  1994. FILE *bftp_io = NULL;
  1995.  
  1996. char *BFTPHelp[] =
  1997. {
  1998.   "Builtin FTP client setup",
  1999.   "You'll need a site where you retrieve your files from. Pick one that is",
  2000.   "close to where you live, and later experiment around to find out which",
  2001.   "one's the best for you.", 0
  2002. };
  2003.  
  2004. int bftp_options()
  2005. {
  2006.   return setup_sitelist("ftpsites", "ftpsite", BFTPHelp);
  2007. }
  2008.  
  2009. int bftp_disconnect()
  2010. {
  2011.   Connected = 0;
  2012.  
  2013.   if (bftp_io)
  2014.     fclose(bftp_io);
  2015.   bftp_io = NULL;
  2016.  
  2017.   return 0;
  2018. }
  2019.  
  2020. int bftp_close()
  2021. {
  2022.   return bftp_disconnect();
  2023. }
  2024.  
  2025. /* Send FTP command and wait for reply. Returns 0 on failure. */
  2026. int bftp_cmd(cmd)
  2027.   char *cmd;
  2028. {
  2029.   char buf[256];
  2030.   int result;
  2031.  
  2032.   if (!bftp_io)
  2033.     return 0;
  2034.  
  2035.   if (cmd) {
  2036.     fflush(bftp_io);
  2037.     rewind(bftp_io);
  2038.     fputs(cmd, bftp_io);
  2039.   }
  2040.   fflush(bftp_io);
  2041.   rewind(bftp_io);
  2042.   if (!fgets(buf, sizeof(buf), bftp_io))
  2043.     return 0;
  2044.  
  2045.   result = myatoi(buf);
  2046.  
  2047.   while ((buf[3] != ' ') || (myatoi(buf) != result)) {
  2048.     if (!fgets(buf, sizeof(buf), bftp_io))
  2049.       return 0;
  2050.   }
  2051.  
  2052.   return (result >= 100) && (result < 400);
  2053. }
  2054.  
  2055. int bftp_getdataconnection()
  2056. {
  2057.   struct sockaddr_in sin;
  2058.   struct hostent *hp;
  2059.   int d, i;
  2060.   unsigned char *a, *p;
  2061.   char buf[80];
  2062.  
  2063.   gethostname(buf, sizeof(buf));
  2064.   hp = gethostbyname(buf);
  2065.  
  2066.   /* Port is not set, let system choose */
  2067.   memset((char *) &sin, '\0', sizeof(sin));
  2068.   memcpy((char *) &sin.sin_addr, hp->h_addr, hp->h_length);
  2069.   sin.sin_family = hp->h_addrtype;
  2070.  
  2071.   if ((d = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
  2072.     return -1;
  2073.  
  2074.   i = sizeof(sin);
  2075.   if ((bind(d, (struct sockaddr *) & sin, i) < 0) ||
  2076.       (getsockname(d, (struct sockaddr *) & sin, &i) < 0) ||
  2077.       (listen(d, 1) < 0)) {
  2078.     close(d);
  2079.     return -1;
  2080.   }
  2081.   a = (unsigned char *) &sin.sin_addr;
  2082.   p = (unsigned char *) &sin.sin_port;
  2083.  
  2084.   sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\n", a[0], a[1], a[2], a[3], p[0], p[1]);
  2085.   if (!bftp_cmd(buf)) {
  2086.     close(d);
  2087.     return -1;
  2088.   }
  2089.   return d;
  2090. }
  2091.  
  2092. int bftp_getfile(remote, local, size, progress)
  2093.   char *remote, *local;
  2094.   int size, (*progress) ();
  2095. {
  2096.   FILE *out = NULL;
  2097.   int s = -1, d = -1, i, got = 0, result = 0;
  2098.   char *buf, *msg = NULL, tmp[80];
  2099.   struct sockaddr_in sin;
  2100.  
  2101.   if (!Connected)
  2102.     return 0;
  2103.  
  2104.   buf = salloc(BFTP_BUFSIZE);
  2105.  
  2106.   sprintf(buf, "Retrouve %s...", remote);
  2107.   progress(buf);
  2108.  
  2109.   if ((s = bftp_getdataconnection()) >= 0) {
  2110.     sprintf(buf, "RETR %s\n", remote);
  2111.     if (bftp_cmd(buf)) {
  2112.       i = sizeof(sin);
  2113.       if ((d = accept(s, (struct sockaddr *) & sin, &i)) >= 0) {
  2114.     if ((out = fopen(local, "w"))) {
  2115.       int len, k, start = time(NULL), t;
  2116.       float kps;
  2117.  
  2118.       while ((len = read(d, buf, BFTP_BUFSIZE)) > 0) {
  2119.         if (fwrite(buf, len, 1, out) != 1) {
  2120.           close(s);
  2121.           fclose(out);
  2122.           msg = "Impossible d'ecrire le fichier local";
  2123.           break;
  2124.         }
  2125.         got += len;
  2126.  
  2127.         if (progress) {
  2128.           k = (got + 512) / 1024;
  2129.           kps = (float)got / (float)((t = time(NULL) - start) ? t * 1024 : 1024);
  2130.           kps = (int)(kps*10.0) / 10.0;
  2131.  
  2132.           if (size > 0)
  2133.         sprintf(tmp, "Récupère %s, %4dK/%4dK (%#3.3g Kbyte/s)",
  2134.             remote, k, (size + 512) / 1024, kps);
  2135.           else
  2136.         sprintf(tmp, "Récupère %s, %4dK (%#3.3g Kbyte/s)", remote, k, kps);
  2137.  
  2138.           progress(tmp);
  2139.         }
  2140.       }
  2141.  
  2142.       if (bftp_cmd(NULL) && ((size <= 0) || (got == size)))
  2143.         result = 1;
  2144.       else {
  2145.         sprintf(buf, "Erreur: sur le fichier %s (pris %d octets au lieu de %d)", 
  2146.             remote, got, size);
  2147.         msg = buf;
  2148.       }
  2149.     } else
  2150.       msg = "Peux pas créer le fichier local";
  2151.       } else
  2152.     msg = "Je ne peux pas faire de connexion avec le site ftp";
  2153.     } else
  2154.       msg = "Je ne peux pas récupérer le fichier";
  2155.   } else
  2156.     msg = "Je ne peux commencer la connexion avec le site ftp";
  2157.  
  2158.   if (progress && msg) {
  2159.     sleep(1);
  2160.     progress(msg);
  2161.     sleep(2);
  2162.   }
  2163.  
  2164.   if (d >= 0)
  2165.     close(d);
  2166.   if (s >= 0)
  2167.     close(s);
  2168.   if (out)
  2169.     fclose(out);
  2170.   free(buf);
  2171.  
  2172.   return result;
  2173. }
  2174.  
  2175. int bftp_connect(progress, remote)
  2176.   int (*progress) ();
  2177.   int remote;
  2178. {
  2179.   char *parts[10], buf[100], *msg = NULL,passwd[32];
  2180.   struct servent *sp;
  2181.   int s, port = 21;
  2182.   char *site;
  2183.   
  2184.   sprintf(passwd,"PASS %s@\n",getenv("USER")); 
  2185.  
  2186.   if (Connected)
  2187.     return 1;
  2188.   Connected = 1;
  2189.  
  2190.   str_sitesplit(option_get("ftpsite"), parts);
  2191.  
  2192.   if (remote)
  2193.     sprintf(buf, "Connexion à %s (site maître)", site=parts[*parts[4]? 4:1]);
  2194.   else
  2195.     sprintf(buf, "Connexion à %s", site=parts[1]);
  2196.  
  2197.   progress(buf);
  2198.  
  2199.   if ((sp = getservbyname("ftp", "tcp")))
  2200.     port = ntohs(sp->s_port);
  2201.  
  2202.   if ((s = tcp_createsocket(site, port)) >= 0) {
  2203.     if ((bftp_io = fdopen(s, "r+"))) {
  2204.       sprintf (buf, "CWD %s\n", *parts[3] ? parts[3] : "pub/aminet");
  2205.       if (bftp_cmd(NULL) &&
  2206.       bftp_cmd("USER ftp\n") &&
  2207.       bftp_cmd(passwd) &&
  2208.       bftp_cmd( buf ) &&
  2209.       bftp_cmd("TYPE I\n"))
  2210.     return 0;
  2211.       else
  2212.     msg = "L'accès au site n'a pu s'effectuer. Peut-être trop d'utilisateurs";
  2213.     } else {
  2214.       close(s);
  2215.       msg = "Impossible de communiquer avec le site FTP";
  2216.     }
  2217.   } else
  2218.     msg = "Impossible de se connecter au site FTP.";
  2219.  
  2220.   bftp_close();
  2221.  
  2222.   if (msg) {
  2223.     sleep(1);
  2224.     progress(msg);
  2225.     sleep(2);
  2226.   }
  2227.  
  2228.   return 1;
  2229. }
  2230.  
  2231. int bftp_remopen(tfh, remote, pack, progress)
  2232.   TEMPFILE *tfh;
  2233.   char *remote, *pack;
  2234.   int (*progress) ();
  2235. {
  2236.   char buf[200];
  2237.  
  2238.   tfh->fh = NULL;
  2239.   temp_name(tfh->name, "RECENT");
  2240.   strcat(tfh->name, pack);
  2241.   tfh->cleanup = temp_delete;
  2242.  
  2243.   unlink(tfh->name);
  2244.  
  2245.   sprintf(buf, "%s%s", remote, pack);
  2246.  
  2247.   if (bftp_getfile(buf, tfh->name, 0, progress)) {
  2248.     if (*pack) {
  2249.       temp_name(tfh->name, "RECENT");
  2250.       unlink(tfh->name);
  2251.  
  2252.       progress ("Décompression");
  2253.       if (pack[2]) {
  2254.         sprintf(buf,"gzip -d <%s%s >%s", tfh->name, pack, tfh->name);
  2255.       } else {
  2256.         sprintf(buf,"uncompress <%s%s >%s", tfh->name, pack, tfh->name);
  2257.       }
  2258.       system(buf);
  2259.       sprintf(buf,"%s%s",tfh->name,pack);
  2260.       unlink (buf);
  2261.     }
  2262.     tfh->fh = fopen(tfh->name, "r");
  2263.   }
  2264.   NoFilesString = "Je ne peux pas télécharger l'INDEX";
  2265.  
  2266.   return 0;
  2267. }
  2268.  
  2269. int bftp_download(remote, locdir, size, progress)
  2270.   char *remote, *locdir;
  2271.   int size, (*progress) ();
  2272. {
  2273.   char buf[200];
  2274.  
  2275.   mystrcpy(buf, locdir);
  2276.   tackon(buf, basename(remote));
  2277.  
  2278.   bftp_getfile(remote, buf, size, progress);
  2279.  
  2280.   return 0;
  2281. }
  2282.  
  2283. int bftp_init()
  2284. {
  2285.   Connected = 0;
  2286.   trans_options = bftp_options;
  2287.   trans_connect = bftp_connect;
  2288.   trans_disconnect = bftp_disconnect;
  2289.   trans_remopen = bftp_remopen;
  2290.   trans_download = bftp_download;
  2291.   trans_close = bftp_close;
  2292.  
  2293.   return 0;
  2294. }
  2295.  
  2296. #endif
  2297.  
  2298. /* =================================FIND CLIENT=============================== */
  2299. #ifndef NO_FIND_CLIENT
  2300.  
  2301. #define FINDD_PORT 1848
  2302.  
  2303. FILE *findd_fgrep(host, string, max)
  2304.   char *host, *string;
  2305.   int max;
  2306. {
  2307.   int fd;
  2308.   char buf[200];
  2309.   int port= FINDD_PORT;
  2310.  
  2311.   sprintf(buf, "Connexion au serveur de recherche %s...", host);
  2312.   disp_clear();
  2313.   disp_report(buf);
  2314.  
  2315.   if ((fd = tcp_createsocket(host, port)) >= 0) {
  2316.     sprintf(buf, "max %d ; ADTfind %s ; quit\r\n", max, string);
  2317.     write(fd, buf, strlen(buf));
  2318.     return fdopen(fd, "r");
  2319.   } else {
  2320.     sleep(1);
  2321.     disp_report("Could not connect to find server");
  2322.     sleep(2);
  2323.   }
  2324.  
  2325.   return NULL;
  2326. }
  2327.  
  2328.  
  2329. #else
  2330.  
  2331. char *NoFinddHelp[] =
  2332. {
  2333.   "Desolé pas de daemon de recherche compilé dans cette version", 0
  2334. };
  2335.  
  2336. FILE *findd_fgrep(host, port, string, max)
  2337.   char *host, *string;
  2338.   int port, max;
  2339. {
  2340.   disp_confirm(NoFinddHelp, 0);
  2341.   return NULL;
  2342. }
  2343.  
  2344. #endif
  2345.  
  2346. /* =================================MAIN PROGRAM============================== */
  2347.  
  2348. int adt_connect (progress, remote)
  2349.   int (*progress) ();
  2350.   int remote;
  2351. {
  2352.   return trans_connect (progress, remote);
  2353. }
  2354.  
  2355. int adt_disconnect ()
  2356. {
  2357.   trans_disconnect ();
  2358.   return 0;
  2359. }
  2360.  
  2361. #ifdef SIGINT
  2362. void adt_breakcheck (sig)
  2363.   int sig;
  2364. {
  2365.   signal(SIGINT, adt_breakcheck);
  2366.  
  2367.   if (!MaskSIGINT || (MaskSIGINT && GotSIGINT))
  2368.     exit_adt ("Abandonné");
  2369.   GotSIGINT=1;
  2370. }
  2371. #endif
  2372.  
  2373.  
  2374. int tagcurrent()
  2375. {
  2376.   if (Vis->num && Vis->list[Vis->current])
  2377.     Vis->list[Vis->current]->tagged ^= 1;
  2378.  
  2379.   return 0;
  2380. }
  2381.  
  2382. int tagall()
  2383. {
  2384.   int tag, i;
  2385.   ENTRY **e = Vis->list;
  2386.  
  2387.   if (Vis->num) {
  2388.     tag = Vis->list[0]->tagged ^ 1;
  2389.     for (i = 0; i < Vis->num; i++)
  2390.       e[i]->tagged = tag;
  2391.   }
  2392.   return 0;
  2393. }
  2394.  
  2395. char transferdesc[200];
  2396.  
  2397. char *transferstr()
  2398. {
  2399.   char *proc = Action ? (Action == 2 ? "unpack" : "send") : "none";
  2400.  
  2401.   sprintf(transferdesc,
  2402.       "Action: %-6s  Chemin: %-16.16s  Readmes: %c  SousRep: %c  Verbose: %c",
  2403.       proc, Path, Readme ? 'y' : 'n', Flat ? 'n' : 'y', Silent ? 'n' : 'y');
  2404.  
  2405.   return transferdesc;
  2406. }
  2407.  
  2408. int progress_dummy()
  2409. {
  2410.   return 0;
  2411. }
  2412.  
  2413. int make_dirs(path)
  2414.   char *path;
  2415. {
  2416.   char buf[200], *s = path, *d = buf;
  2417.  
  2418.   do {
  2419.     while (*s && *s != '/')
  2420.       *d++ = *s++;
  2421.  
  2422.     *d = 0;
  2423.  
  2424.     if (access(buf, 3))
  2425.       makedir(buf, 0755);
  2426.  
  2427.     if (*s)
  2428.       *d++ = *s++;
  2429.   } while (*s);
  2430.  
  2431.   return 0;
  2432. }
  2433.  
  2434.  
  2435. int do_action(locdir, remname)
  2436.   char *locdir, *remname;
  2437. {
  2438.   char locname[200];
  2439.   char buf[200];
  2440.   int len;
  2441.  
  2442.   mystrcpy(locname, locdir);
  2443.   tackon(locname, basename(remname));
  2444.  
  2445.   if (Action == 1) {
  2446.     sprintf(buf, "%s %s", option_get("send"), locname);
  2447.     system(buf);
  2448.     sleep(2);
  2449.     disp_refresh();
  2450.   }
  2451.   if (Action == 2) {
  2452.     len = mystrlen(locname);
  2453.  
  2454.     if (len > 4 && !mystricmp(locname + len - 4, ".lha")) {
  2455.       puts("");
  2456.       sprintf(buf, "cd %s;lha e %s", locdir, locname);
  2457.       system(buf);
  2458.       disp_refresh();
  2459.     } else if (len > 2 && !mystrcmp(locname + len - 2, ".Z")) {
  2460.       puts("");
  2461.       sprintf(buf, "cd %s;uncompress %s", locdir, locname);
  2462.       system(buf);
  2463.       disp_refresh();
  2464.     } else if (len > 3 && !mystrcmp(locname + len - 3, ".gz")) {
  2465.       puts("");
  2466.       sprintf(buf, "cd %s;gzip -d %s", locdir, locname);
  2467.       system(buf);
  2468.       disp_refresh();
  2469.     }
  2470.   }
  2471.   return 0;
  2472. }
  2473.  
  2474. int get_files(progress, showfile)
  2475.   int (*progress) (), (*showfile) ();
  2476. {
  2477.   ENTRY *e;
  2478.   char locdir[200], remname[200];
  2479.   int i, p, err = 0, n;
  2480.  
  2481.   if (Silent)
  2482.     progress = progress_dummy;
  2483.  
  2484.  
  2485.   MaskSIGINT = 1;
  2486.  
  2487.   for (p=0; p<2; p++) {
  2488.  
  2489.     for (i = n = 0; i < Vis->num; i++)
  2490.       if ( (Vis->list[i]->status & 1) == p)
  2491.         n++;
  2492.  
  2493.     if (!n)
  2494.       continue;
  2495.  
  2496.     if (adt_connect(progress, p))
  2497.       continue;
  2498.  
  2499.     for (i = 0; i < Vis->num; i++) {
  2500.       e = Vis->list[i];
  2501.  
  2502.       if ((e->status & 1) != p)
  2503.         continue;
  2504.  
  2505.       showfile (Vis, i);
  2506.  
  2507.       mystrcpy(locdir, option_get("dlpath"));
  2508.       glob_path(locdir);
  2509.       if (!Flat)
  2510.         tackon(locdir, e->dir);
  2511.       make_dirs(locdir);
  2512.  
  2513.       mystrcpy(remname, e->dir);
  2514.       tackon(remname, e->file);
  2515.  
  2516.       if (!*locdir)
  2517.         mystrcpy(locdir, CURDIR);
  2518.  
  2519.       if ((err = trans_download(remname, locdir, e->size, progress)))
  2520.         break;
  2521.  
  2522.       if ( GotSIGINT )
  2523.         break;
  2524.  
  2525.       do_action(locdir, remname);
  2526.  
  2527.       if (Readme) {
  2528.         mystrcpy(remname, e->dir); 
  2529.         tackon(remname, get_readme(e));
  2530.  
  2531.         if ((err = trans_download(remname, locdir, e->readmesize, progress)))
  2532.       break;
  2533.  
  2534.         if ( GotSIGINT )
  2535.           break;
  2536.  
  2537.         do_action(locdir, remname);
  2538.       }
  2539.  
  2540.       if (GotSIGINT) {
  2541.         progress ("Interrompu");
  2542.         break;
  2543.       }
  2544.  
  2545.       e->tagged = 0;
  2546.       showfile (Vis, i);
  2547.  
  2548.     }
  2549.  
  2550.     adt_disconnect();
  2551.  
  2552.     if (err)
  2553.       disp_status("Erreur durant la récupération");
  2554.  
  2555.   }
  2556.  
  2557.   MaskSIGINT = GotSIGINT = 0;
  2558.  
  2559.   return 0;
  2560. }
  2561.  
  2562. int find_string(string, progress)
  2563.   char *string;
  2564.   int (*progress) ();
  2565. {
  2566.   FILE *fh;
  2567.   char *site;
  2568.   char *parts[10];
  2569.  
  2570.   NoFilesString = "Pas de fichier trouvé";
  2571.   Vis->sel = "Found files";
  2572.  
  2573.   if (!*option_get("findmethod"))
  2574.     if (setup_findmethod())
  2575.       return 1;
  2576.  
  2577.   switch (option_getnum("findmethod")) {
  2578.  
  2579.   case 0:
  2580.  
  2581.     GotComplete = GotLocal = GotRecent = 0;
  2582.  
  2583.     site = option_get("findsite");
  2584.  
  2585.     progress("Je cherche...");
  2586.  
  2587.     str_sitesplit(site, parts);
  2588.  
  2589.     fh = findd_fgrep(parts[1], string, 100);
  2590.  
  2591.     if (fh) {
  2592.       e_freeall();
  2593.       fgets(parsebuf, 120, fh);
  2594.       read_adt_v2(fh);
  2595.       allvisible();
  2596.       fclose(fh);
  2597.     }
  2598.     Vis->sel = "Fichier trouvés";
  2599.     sort_list(Vis, &sort_dir);
  2600.  
  2601.     break;
  2602.  
  2603.   case 1:
  2604.  
  2605.     get_sitelocal();
  2606.     progress("Je cherche...");
  2607.     findstr(string);
  2608.     break;
  2609.  
  2610.   case 2:
  2611.  
  2612.     get_complete();
  2613.     progress("Je cherche...");
  2614.     findstr(string);
  2615.     break;
  2616.  
  2617.   }
  2618.  
  2619.   return 0;
  2620. }
  2621.  
  2622. int print_listing(width)
  2623.   int width;
  2624. {
  2625.   ENTRY **list = Vis->list;
  2626.   FILE *f;
  2627.   char file[300];
  2628.   int i;
  2629.   long now = time(NULL);
  2630.  
  2631.   mystrcpy (file, glob_path( option_get("printer")));
  2632.  
  2633.   if (!*file || !(f = fopen(file, "w")))
  2634.     return 0;
  2635.  
  2636.   if (width == 1) {
  2637.  
  2638.     fputs("|Fichier             Repertoire Tail Description\n", f);
  2639.     fputs("|------------------- ---------- ---- -----------\n", f);
  2640.  
  2641.   } else {
  2642.  
  2643.     fputs("|Fichie              Repertoire Tail Age  Description\n", f);
  2644.     fputs("|------------------- ---------- ---- ---  -----------\n", f);
  2645.  
  2646.   }
  2647.  
  2648.  
  2649.   for (i = 0; i < Vis->num; i++) {
  2650.  
  2651.     if (width == 1) {
  2652.  
  2653.       fprintf(f, "%-20.20s %-10.10s %4.4s%c%-42.42s\n",
  2654.           list[i]->file,
  2655.           list[i]->dir,
  2656.           str_ksize(list[i]->size),
  2657.           list[i]->readmesize > 100 ? '+' : ' ',
  2658.           list[i]->desc);
  2659.  
  2660.     } else {
  2661.  
  2662.       fprintf(f, "%-20.20s %-10.10s %4.4s %3.3d %c%-.80s\n",
  2663.           list[i]->file,
  2664.           list[i]->dir,
  2665.           str_ksize(list[i]->size),
  2666.           (now - list[i]->time) / 86400,
  2667.           list[i]->readmesize > 100 ? '+' : ' ',
  2668.           list[i]->desc);
  2669.  
  2670.     }
  2671.   }
  2672.  
  2673.   fclose(f);
  2674.  
  2675.   return 0;
  2676. }
  2677.  
  2678.  
  2679. int display_remote(name, title)
  2680.   char *name;
  2681.   char *title;
  2682. {
  2683.   TEMPFILE tfh;
  2684.   char **strings;
  2685.  
  2686.   trans_remopen(&tfh, name, "", disp_status);
  2687.  
  2688.   if (tfh.fh) {
  2689.  
  2690.     strings = read_file(tfh.fh, title);
  2691.     disp_more(strings);
  2692.     free_file(strings);
  2693.     tclose(&tfh);
  2694.  
  2695.   } else {
  2696.  
  2697.     disp_status ("Je ne peux ouvrir le fichier lointain");
  2698.  
  2699.   }
  2700.  
  2701.   return 0;
  2702. }
  2703.  
  2704.  
  2705. /* =================================CURSES PACKAGE============================ */
  2706. #ifndef NO_CURSES
  2707.  
  2708. int debug(str)
  2709.   char *str;
  2710. {
  2711.   move(0, 0);
  2712.   addstr(str);
  2713.   refresh();
  2714.   sleep(1);
  2715.   return 0;
  2716. }
  2717.  
  2718. int cur_dispinit()
  2719. {
  2720.   initscr();
  2721.   nl();
  2722.   noecho();
  2723.   cbreak();
  2724.   return 0;
  2725. }
  2726.  
  2727. int cur_getchar()
  2728. {
  2729.   int c=getchr();
  2730. #ifdef SHOW_KEYS
  2731.   static int foo;
  2732.   char buf[20];
  2733.   sprintf(buf,"%2x",c);
  2734.   move(0, (foo+=2)%8);
  2735.   addstr(buf);
  2736. #endif
  2737.  
  2738.   return c;
  2739. }
  2740.  
  2741.  
  2742. #define Y_LISTTITLE 2
  2743. #define Y_LISTSTART 3
  2744. #define Y_LISTEND   (LINES-6)
  2745. #define Y_INFO      (LINES-5)
  2746. #define Y_COMMAND   (LINES-3)
  2747. #define Y_STATUS    (LINES-1)
  2748.  
  2749. #define X_COMMAND   9
  2750.  
  2751.  
  2752. int cur_helpblock(help)
  2753.   char **help;
  2754. {
  2755.   int i, m = str_shift(str_longest(help), COLS);
  2756.  
  2757.   clear();
  2758.  
  2759.   move(0, 0);
  2760.   addstr(str_center(help[0], COLS));
  2761.  
  2762.   for (i = 0; help[i + 1]; i++) {
  2763.     move(2 + i, m);
  2764.     addstr(help[i + 1]);
  2765.   }
  2766.  
  2767.   return i;
  2768. }
  2769.  
  2770. char *cur_getstringat(buf, x, y)
  2771.   char *buf;
  2772.   int x, y;
  2773. {
  2774.   char bak[300];
  2775.   int c, l = strlen(buf), p = l, i;
  2776.  
  2777.   mystrcpy(bak, buf);
  2778.  
  2779.   move(y, x);
  2780.   addstr(buf);
  2781.  
  2782.   for (;;) {
  2783.     move(y, x + p);
  2784.     refresh();
  2785.     switch (c = inp_getchr()) {
  2786.  
  2787.     case 1:
  2788.       p = 0;
  2789.       break;
  2790.  
  2791.     case 5:
  2792.       p = l;
  2793.       break;
  2794.  
  2795.     case 8: case 127:
  2796.       if (p == 0)
  2797.     break;
  2798.  
  2799.       for (i = --p; i < l; i++)
  2800.     buf[i] = buf[i + 1];
  2801.       buf[--l] = ' ';
  2802.  
  2803.       move(y, x + p);
  2804.       addstr(buf + p);
  2805.       buf[l] = 0;
  2806.       break;
  2807.  
  2808.     case 13: case 10:
  2809.       goto done;
  2810.  
  2811.     case K_RIGHT:
  2812.       if (p < l)
  2813.     p++;
  2814.       break;
  2815.  
  2816.     case K_LEFT:
  2817.       if (p > 0)
  2818.     p--;
  2819.       break;
  2820.  
  2821.     default:
  2822.       if (c < ' ' || c > 127 || l > COLS - x - 1)
  2823.     break;
  2824.  
  2825.       for (i = l; i > p; i--)
  2826.     buf[i + 1] = buf[i];
  2827.       buf[++l] = 0;
  2828.       buf[p] = c;
  2829.  
  2830.       move(y, x + p);
  2831.       addstr(buf + p);
  2832.       p++;
  2833.       break;
  2834.     }
  2835.  
  2836.   }
  2837.  
  2838. done:
  2839.   return buf;
  2840.  
  2841. }
  2842.  
  2843. int OptLen;
  2844.  
  2845. char *cur_inputstr(buf, help)
  2846.   char *buf, **help;
  2847. {
  2848.   int x = str_shift(str_longest(help), COLS);
  2849.   int y = 3 + cur_helpblock(help);
  2850.  
  2851.   move(y, x);
  2852.   addstr("> ");
  2853.  
  2854.   return cur_getstringat(buf, x + 2, y);
  2855. }
  2856.  
  2857.  
  2858. char *cur_getstring(buf)
  2859.   char *buf;
  2860. {
  2861.   int y = Y_COMMAND, x = X_COMMAND + OptLen;
  2862.   char *ret;
  2863.  
  2864.   move(y, x);
  2865.   addstr(": ");
  2866.   x += 2;
  2867.   OptLen += 2;
  2868.  
  2869.   ret = cur_getstringat(buf, x, y);
  2870.  
  2871.   OptLen = x + strlen(buf) + 1;
  2872.  
  2873.   return ret;
  2874. }
  2875.  
  2876. char dbuf[300];
  2877.  
  2878. int cur_displist(list)
  2879.   LIST *list;
  2880. {
  2881.   int i;
  2882.   char *line;
  2883.   char *t = NULL, c = 0;
  2884.  
  2885.   Window = Y_LISTEND - list->top;
  2886.  
  2887.   if (!list->num) {
  2888.     move(LINES / 2, 0);
  2889.     addstr(str_center(NoFilesString, COLS - 1));
  2890.     return 0;
  2891.   }
  2892.  
  2893.   list->offset = list->current / Window * Window;
  2894.  
  2895.   for (i = 0; i < Window; i++) {
  2896.     line = list->disp(list->list, list->offset + i, list->num, dbuf, Width);
  2897.  
  2898.     if (*line)
  2899.       move(list->top + i, list->type ? (Width - strlen(line)) / 2 : 0);
  2900.     else {
  2901.       move(list->top + i, 0);
  2902.       clrtoeol();
  2903.     }
  2904.  
  2905.     if (list->offset + i != list->current) {
  2906.       addstr(line);
  2907.     } else {
  2908.       if (list->type == 0) {
  2909.     for (t = line + 1; *t != ' '; t++);
  2910.     c = t[1];
  2911.     t[1] = 0;
  2912.       }
  2913.       standout();
  2914.       addstr(line);
  2915.       standend();
  2916.  
  2917.       if (list->type == 0) {
  2918.     t[1] = c;
  2919.     addstr(t + 1);
  2920.       }
  2921.     }
  2922.   }
  2923.  
  2924.   return 0;
  2925. }
  2926.  
  2927. int cur_dispfiles(list)
  2928.   LIST *list;
  2929. {
  2930.   Window = Y_LISTEND - Y_LISTSTART;
  2931.  
  2932.   if (list == Vis) {
  2933.     move(0, 0);
  2934.     addstr(str_topline(dbuf, Width - 1, list));
  2935.   }
  2936.  
  2937.   cur_displist(list);
  2938.  
  2939.   return 0;
  2940. }
  2941.  
  2942.  
  2943. int cur_dispmask()
  2944. {
  2945.   Window = Y_LISTEND - Y_LISTSTART;
  2946.  
  2947.   Vis->disp = str_entry;
  2948.   Vis->top = Y_LISTSTART;
  2949.  
  2950.   clear();
  2951.   move(Y_LISTTITLE, 0);
  2952.   addstr(str_titles(dbuf, Width - 1));
  2953.  
  2954.   cur_dispfiles(Vis);
  2955.  
  2956.   move(Y_INFO, 0);
  2957.   addstr(str_center(Vis->cmds, Width - 1));
  2958.  
  2959.   move(Y_COMMAND, 0);
  2960.   addstr("Commande:  ");
  2961.  
  2962.   refresh();
  2963.   return 0;
  2964. }
  2965.  
  2966. int cur_mark(list, on)
  2967.   LIST *list;
  2968.   int on;
  2969. {
  2970.   char *t = NULL, *line;
  2971.  
  2972.   line = list->disp(list->list, list->current, list->num, dbuf, Width - 1);
  2973.  
  2974.   if (list->type == 0) {
  2975.     for (t = line + 1; *t != ' '; t++);
  2976.     t[1] = 0;
  2977.   }
  2978.   move(list->top + list->current - list->offset,
  2979.        list->type ? (Width - strlen(line)) / 2 : 0);
  2980.  
  2981.   if (on)
  2982.     standout();
  2983.   addstr(line);
  2984.   if (on)
  2985.     standend();
  2986.  
  2987.   if (list->type == 0)
  2988.     t[1] = ' ';
  2989.  
  2990.   return 0;
  2991. }
  2992.  
  2993. int cur_gomid(list)
  2994.   LIST *list;
  2995. {
  2996.   int left = list->num - list->offset;
  2997.  
  2998.   list->current = list->offset + (left < Window ? left : Window) / 2;
  2999.   return 0;
  3000. }
  3001.  
  3002.  
  3003. int cur_moveto(list, pos)
  3004.   LIST *list;
  3005.   int pos;
  3006. {
  3007.   if (!list->num)
  3008.     return 0;
  3009.  
  3010.   if (pos < 0)
  3011.     pos = 0;
  3012.  
  3013.   if (pos > list->num - 1)
  3014.     pos = list->num - 1;
  3015.  
  3016.   if (pos == list->current)
  3017.     return 0;
  3018.  
  3019.   cur_mark(list, 0);
  3020.   list->current = pos;
  3021.  
  3022.   if (pos / Window * Window == list->offset) {
  3023.  
  3024.     cur_mark(list, 1);
  3025.  
  3026.   } else {
  3027.  
  3028.     list->offset = pos / Window * Window;
  3029.     cur_dispfiles(list);
  3030.  
  3031.   }
  3032.  
  3033.   return 0;
  3034. }
  3035.  
  3036. int cur_listnav(list, c)
  3037.   LIST *list;
  3038.   int c;
  3039. {
  3040.   switch (c) {
  3041.   case K_DOWN:
  3042.   case K_CTRL + 'N':
  3043.   case 'j':
  3044.     cur_moveto(list, list->current + 1);
  3045.     break;
  3046.  
  3047.   case K_UP:
  3048.   case K_CTRL + 'P':
  3049.   case 'k':
  3050.     cur_moveto(list, list->current - 1);
  3051.     break;
  3052.  
  3053.   case K_RIGHT:
  3054.   case ' ':
  3055.   case K_CTRL + 'F':
  3056.     cur_moveto(list, (list->current + Window)/Window*Window);
  3057.     break;
  3058.  
  3059.   case K_LEFT:
  3060.   case K_CTRL + 'H':
  3061.   case K_CTRL + 'B':
  3062.   case 'b':
  3063.     cur_moveto(list, (list->current - Window)/Window*Window);
  3064.     break;
  3065.  
  3066.   case K_CTRL + 'I':
  3067.     cur_moveto(list, list->current + 5);
  3068.     break;
  3069.  
  3070.   case '<':
  3071.     cur_moveto(list, 0);
  3072.     break;
  3073.  
  3074.   case '>':
  3075.     cur_moveto(list, list->num - 1);
  3076.     break;
  3077.  
  3078.   case K_CTRL + 'L':
  3079.     touchwin (stdscr);
  3080.     refresh();
  3081.     break;
  3082.  
  3083.   default:
  3084.     return 0;
  3085.  
  3086.   }
  3087.  
  3088.   return 1;
  3089. }
  3090.  
  3091. int cur_choice(help, list)
  3092.   char **help;
  3093.   LIST *list;
  3094. {
  3095.   char *cmd = "Sélectionner à l'aide des touches flèchées. RETURN confirme et q quitte";
  3096.   int c, ret = 0;
  3097.  
  3098.   list->top = 3 + cur_helpblock(help);
  3099.  
  3100.   cur_displist(list);
  3101.  
  3102.   move(Y_COMMAND, list->type ? (Width - strlen(cmd)) / 2 : 0);
  3103.   addstr(cmd);
  3104.  
  3105.   refresh();
  3106.  
  3107.   for (;;) {
  3108.     c = inp_getchr();
  3109.     if (c == 'q')
  3110.       return -1;
  3111.     if (c == 10 || c == 13) {
  3112.       ret = list->current;
  3113.       goto done;
  3114.     }
  3115.     cur_listnav(list, c);
  3116.     move(Y_COMMAND, strlen(cmd) + (list->type ? (Width - strlen(cmd)) / 2 : 0));
  3117.     refresh();
  3118.   }
  3119.  
  3120. done:
  3121.   return ret;
  3122. }
  3123.  
  3124. int cur_cmdstr(string)
  3125.   char *string;
  3126. {
  3127.   move(Y_COMMAND, X_COMMAND);
  3128.   addstr(string);
  3129.   refresh();
  3130.   OptLen = strlen(string);
  3131.  
  3132.   return 0;
  3133. }
  3134.  
  3135. int cur_subopt(string)
  3136.   char *string;
  3137. {
  3138.   char buf[200], *b = buf;
  3139.   int c, i;
  3140.  
  3141.   cur_cmdstr(string);
  3142.  
  3143.   c = inp_getchr();
  3144.  
  3145.   for (i = 0; string[i] && string[i] != ' '; i++)    /* view   */
  3146.     *b++ = string[i];
  3147.   *b++ = ' ';
  3148.  
  3149.   for (i = strlen(string) - 1; i > 0; i--)    /* a)ll   */
  3150.     if (string[i] == ')' && string[i - 1] == c)
  3151.       break;
  3152.  
  3153.   if (i > 0) {            /* all    */
  3154.     *b++ = string[++i - 2];
  3155.     while (string[i] && string[i] != ' ')
  3156.       *b++ = string[i++];
  3157.   }
  3158.   OptLen = b - buf;
  3159.  
  3160.   while (b < buf + strlen(string))    /* blanks */
  3161.     *b++ = ' ';
  3162.   *b++ = 0;
  3163.  
  3164.   move(Y_COMMAND, X_COMMAND);
  3165.   addstr(buf);
  3166.   move(Y_COMMAND, X_COMMAND + OptLen);
  3167.   refresh();
  3168.   return c;
  3169. }
  3170.  
  3171. char statusbuf[300];
  3172.  
  3173.  
  3174. int cur_statusat(string, y)
  3175.   char *string;
  3176.   int y;
  3177. {
  3178.   int i, sh;
  3179.  
  3180.   for (i = 0; i < COLS - 1; i++)
  3181.     statusbuf[i] = ' ';
  3182.   statusbuf[i] = 0;
  3183.  
  3184.   mystrcpy(statusbuf + (sh = str_shift(strlen(string), COLS)), string);
  3185.   statusbuf[strlen(statusbuf)] = ' ';
  3186.  
  3187.   move(y, 0);
  3188.   addstr(statusbuf);
  3189.   move(y, sh + strlen(string));
  3190.   refresh();
  3191.  
  3192.   return 0;
  3193. }
  3194.  
  3195. int cur_status(string)
  3196.   char *string;
  3197. {
  3198.   cur_statusat(string, Y_STATUS);
  3199.  
  3200.   return 0;
  3201. }
  3202.  
  3203. int cur_clear()
  3204. {
  3205.   clear();
  3206.   refresh();
  3207.   return 0;
  3208. }
  3209.  
  3210. int cur_report(string)
  3211.   char *string;
  3212. {
  3213.   cur_statusat(string, LINES / 2);
  3214.   return 0;
  3215. }
  3216.  
  3217. int cur_nosubopt()
  3218. {
  3219.   char buf[200], *b = buf;
  3220.  
  3221.   while (OptLen--)
  3222.     *b++ = ' ';
  3223.   *b++ = 0;
  3224.   move(Y_COMMAND, X_COMMAND);
  3225.   addstr(buf);
  3226.   refresh();
  3227.   cur_status("");
  3228.   return 0;
  3229. }
  3230.  
  3231. int cur_more(strings)
  3232.   char **strings;
  3233. {
  3234.   int i, c, lines, offset = 0, len = str_longest(strings);
  3235.   char buf[100], *title = *strings++;
  3236.  
  3237.   for (lines = 0; strings[lines] || lines == 0; lines++);
  3238.  
  3239.   do {
  3240.     clear();
  3241.  
  3242.     move(0, str_shift(strlen(title), len));
  3243.     standout();
  3244.     addstr(title);
  3245.     standend();
  3246.  
  3247.     for (i = 0; i < LINES - 4 && offset + i < lines; i++) {
  3248.       move(2 + i, 0);
  3249.       addstr(strings[offset + i]);
  3250.     }
  3251.  
  3252.     if (offset + i < lines)
  3253.       sprintf(buf, " -- Encore (%d%%), b)ack, q)uit -- ",
  3254.           (offset + i) * 100 / lines);
  3255.     else
  3256.       mystrcpy(buf, " --- End --- ");
  3257.  
  3258.     move(MYMIN(LINES - 1, 3 + offset + i), str_shift(strlen(buf), len));
  3259.     standout();
  3260.     addstr(buf);
  3261.     standend();
  3262.     refresh();
  3263.  
  3264.     c = inp_getchr();
  3265.     if (c == 27 || c == 'q')
  3266.       break;
  3267.     else if (c == 'b' || c == K_CTRL + 'H')
  3268.       offset = MYMAX(0, offset - (LINES - 4));
  3269.     else
  3270.       offset += LINES - 4;
  3271.  
  3272.   } while (offset < lines);
  3273.  
  3274.   return 0;
  3275. }
  3276.  
  3277.  
  3278. char *MainHelp[] = {
  3279.   "Aminet Download Tool Help",
  3280.   "Welcome to the Aminet Download Tool. You can select, inspect and download",
  3281.   "files here. The command keys available:",
  3282.   "",
  3283.   "cursor    navigate on list",
  3284.   "blank     next page (also cursor right)",
  3285.   "backspace previous page (also cursor left)",
  3286.   "tab       move down five",
  3287.   "<  >      start and end of list",
  3288.   "",
  3289.   "d)ownload receive selected file(s) after setting options",
  3290.   "f)ind     locate a file anywhere on Aminet",
  3291.   "h)elp     this page",
  3292.   "o)ptions  setup page",
  3293.   "p)rint    create a listing on disk or printer",
  3294.   "q)uit     leave, remembering this call",
  3295.   "Q)uit     leave, without remembering this call",
  3296.   "r)eadme   display the .readme of current file",
  3297.   "s)ort     change sorting of displayed list",
  3298.   "t)ag      mark/unmark current file for later download (also RETURN)",
  3299.   "T)ag      mark/unmark all files",
  3300.   "v)iew     select which files to show",
  3301.   "",
  3302.   "Press ? at any submenu to get help about the commands there.",
  3303.   0
  3304. };
  3305.  
  3306. char *ViewHelp[] = {
  3307.   "The v)iew command",
  3308.   "This command selects which files to display in ATD. The suboptions:",
  3309.   "",
  3310.   "a)ll      shows the complete list of all files on Aminet, downloading it",
  3311.   "          first if necessary. No files are hidden.",
  3312.   "d)ir      pick from the currently known files the ones from the directory",
  3313.   "          you specify.",
  3314.   "h)ide     selects one or more directory (separated by commas) that should",
  3315.   "          not be shown. This info is stored in .adtrc on exit",
  3316.   "k)nown    shows all currently known files, including those that are normally",
  3317.   "          hidden",
  3318.   "l)imit    only show the files which have the given string somewhere in their",
  3319.   "          description or file name",
  3320.   "m)arked   only shows the files that have previously been marked using the",
  3321.   "          t)ag command",
  3322.   "n)ew      shows the new files since your previous call minus the hidden ones,",
  3323.   "          downloading the list if necessary",
  3324.   "s)ite     shows the list of files available at the site you are currently",
  3325.   "          connected to",
  3326.   "t)oggle   toggle between the current list and the previously displayed one.",
  3327.   0
  3328. };
  3329.  
  3330. char *SortHelp[] = {
  3331.   "The s)ort command",
  3332.   "Using this command you can select what order the files should be shown by",
  3333.   "",
  3334.   "a)ge      sorts by age, showing the newest files on top",
  3335.   "A)ge      like a)ge but showing the oldest files on top",
  3336.   "d)ir      sorts alphabetically by directory, subsorting by name",
  3337.   "D)ir      like d)ir but reverse order",
  3338.   "n)ame     sorts alphabetically by file name",
  3339.   "N)ame     like n)ame but reverse order",
  3340.   "s)ize     sorts by file size, largest on top",
  3341.   "S)ize     like s)ize, but smallst on top",
  3342.   0
  3343. };
  3344.  
  3345. int cur_editvar(varname, string)
  3346.   char *varname, *string;
  3347. {
  3348.   char buf[100];
  3349.  
  3350.   cur_status(string);
  3351.   mystrncpy(buf, option_get(varname), 99);
  3352.   cur_getstring(buf);
  3353.   option_set(varname, buf);
  3354.   return 0;
  3355. }
  3356.  
  3357. int cur_showfile(list, i)
  3358.   LIST *list;
  3359.   int i;
  3360. {
  3361.   cur_moveto (list, i);
  3362.   cur_mark   (list, 0);
  3363.   cur_mark   (list, 1);
  3364.  
  3365.   return 0;
  3366. }
  3367.  
  3368. char *DownloadHelp[] = {
  3369.   "The d)ownload command",
  3370.   "This command lets you receive files from Aminet. The suboptions:",
  3371.   "",
  3372.   "a)ction   select what to do after the download. Possibilities are either",
  3373.   "          nothing, transfer using zmodem, or archive unpacking",
  3374.   "b)egin    actually perform the download, using the current settings",
  3375.   "          selected by the other keys",
  3376.   "p)ath     lets you enter the destination path for the files, will be",
  3377.   "          created if it does not exist",
  3378.   "q)uit     do not start download, leave all undownloaded files tagged,",
  3379.   "          and return to main files selection page",
  3380.   "r)eadme   toggle between downloading the .readme files along with the",
  3381.   "          archives and not doing so",
  3382.   "s)ubdirs  toggle between putting all files in the same directory vs",
  3383.   "          re-creating the Aminet directory structure",
  3384.   "v)erbose  toggle between quiet and verbose download, where quiet suspends",
  3385.   "          all screen output until all files have been downloaded.",
  3386.   "",
  3387.   "The current settings are displayed in the bottom line. If you want to",
  3388.   "change those settings permanently, use o)ptions d)ownload.",
  3389.   0
  3390. };
  3391.  
  3392. int cur_download()
  3393. {
  3394.   LIST *l;
  3395.   int cont = 1;
  3396.   char path[300];
  3397.  
  3398.   markedextract();
  3399.  
  3400.   l = Vis;
  3401.   Vis = Mark;
  3402.   Mark = l;
  3403.  
  3404.   Flat = option_getnum("flatdl");
  3405.   Readme = option_getnum("readmedl");
  3406.   Silent = option_getnum("silentdl");
  3407.   mystrcpy(Path, option_get("dlpath"));
  3408.  
  3409.   cur_dispmask();
  3410.  
  3411.   do {
  3412.     cur_status(transferstr());
  3413.     cur_cmdstr("");
  3414.  
  3415.     switch (inp_getchr()) {
  3416.     case '?':
  3417.     case 'h':
  3418.       cur_more(DownloadHelp);
  3419.       cur_dispmask();
  3420.       break;
  3421.  
  3422.     case 'p':
  3423.       cur_cmdstr("path");
  3424.       cur_editvar("dlpath", "Entrez le chemin de destination des fichiers");
  3425.       mystrcpy(Path, option_get("dlpath"));
  3426.       mystrcpy(path, Path);
  3427.       make_dirs (glob_path (path));
  3428.       cur_nosubopt();
  3429.       break;
  3430.  
  3431.     case 'b':
  3432.       cur_moveto(Vis, 0);
  3433.       get_files(cur_status, cur_showfile);
  3434.       cur_nosubopt();
  3435.       cont = 0;
  3436.       break;
  3437.  
  3438.     case 'a':
  3439.       Action = ++Action % 3;
  3440.       break;
  3441.     case 'q':
  3442.       cont = 0;
  3443.       break;
  3444.     case 'r':
  3445.       Readme = !Readme;
  3446.       break;
  3447.     case 's':
  3448.       Flat = !Flat;
  3449.       break;
  3450.     case 'v':
  3451.       Silent = !Silent;
  3452.       break;
  3453.     }
  3454.  
  3455.   } while (cont);
  3456.  
  3457.   l = Vis;
  3458.   Vis = Mark;
  3459.   Mark = l;
  3460.  
  3461.   return 0;
  3462. }
  3463.  
  3464. char *OptionsHelp[] = {
  3465.   "The o)ptions command",
  3466.   "Using the o)ptions command you can modify various settings of ADT. They",
  3467.   "will be saved in .adtrc when you leave ADT using the q)uit command, but",
  3468.   "not if you use Q)uit. The settings you can modify are:",
  3469.   "",
  3470.   "c)ompression lets you pick the compression type used for downloading",
  3471.   "             Aminet contents files.",
  3472.   "d)ownload    will pick the defaults for downloading readmes, verbose or",
  3473.   "             quiet download, download path and so on",
  3474.   "f)ind        lets you pick the method used for finding things on Aminet,",
  3475.   "             ie. download and local search vs. using a search server",
  3476.   "m)ethod      will choose the method used to transfer files, e.g. FTP",
  3477.   "             mail server or local files",
  3478.   "p)rint       lets you choose the format of the listings generated by ADT",
  3479.   "             mostly wide vs. narrow format",
  3480.   "s)ite        this lets you pick the location you want to get your files",
  3481.   "             from, for example which FTP site to use", 0
  3482. };
  3483.  
  3484.  
  3485. char *CompressOptHelp[] = {
  3486.   "Compression type",
  3487.   "Please select the compression method to use for transmitting the Aminet",
  3488.   "index files. If you have very fast access (like local files), pick no",
  3489.   "compression, otherwise pick compress, unless you have 'gzip' in your",
  3490.   "path, which compresses even better at the same speed. Note, we're only",
  3491.   "talking about decompression here, its only the choice between different",
  3492.   "versions of the index files in fact.", 0
  3493. }, *CompressList[] = {
  3494.   "  none  ",
  3495.   "compress",
  3496.   "  gzip  ", 0
  3497. };
  3498.  
  3499. char *FlatOptHelp[] = {
  3500.   "Flat or tree download",
  3501.   "Please choose whether to put all downloaded files in the same",
  3502.   "directory or to create the correct subdirectory as on Aminet ",
  3503.   "for each file downloaded", 0
  3504. }, *FlatDlList[] = {
  3505.   "subdir (create subdirs)",
  3506.   "flat   (same directory)", 0
  3507. };
  3508.  
  3509. char *ReadmeOptHelp[] = {
  3510.   "Readme download",
  3511.   "Please choose whether or not to download the .readme files",
  3512.   "along with the archives", 0
  3513. }, *ReadmeDlList[] = {
  3514.   "download archives only",
  3515.   "download .readme files too", 0
  3516. };
  3517.  
  3518. char *QuietOptHelp[] = {
  3519.   "Silent download",
  3520.   "Please choose wheter or not to perform transfers quietly. If you turn on",
  3521.   "quiet mode, no screen output happens until the download is completey over.",
  3522.   "This allows you to interrupt ADT using CTRL-Z and put it in the background",
  3523.   "using 'bg' to download quietly in the background", 0
  3524. }, *QuietDlList[] = {
  3525.   "give progress reports",
  3526.   "download quietly", 0
  3527. };
  3528.  
  3529. char *FindSitesHelp[] = {
  3530.   "Find site",
  3531.   "Here you can pick the find server to use for your queries. Feel free to",
  3532.   "them all and choose the fastest. All find servers have the complete list",
  3533.   "of all Aminet files online", 0
  3534. };
  3535.  
  3536. char FindString[120];
  3537.  
  3538. int cur_cmdkeys(c)
  3539.   int c;
  3540. {
  3541.   char buf[200];
  3542.   SORT *sorttype;
  3543.   int noredraw = 0, width = 0;
  3544.  
  3545.   buf[0] = 0;
  3546.  
  3547.   switch (c) {
  3548.  
  3549.   case 'a':
  3550.     if (Vis->num)
  3551.       cur_download();
  3552.     break;
  3553.  
  3554.   case 'f':
  3555.     cur_cmdstr("find");
  3556.     cur_status("(Utiliser 'adt -f <motclé>' pour la recherche à partir de la ligne shell)");
  3557.     FindString[0] = 0;
  3558.     cur_getstring(FindString);
  3559.     if (*FindString)
  3560.       find_string(FindString, cur_status);
  3561.     break;
  3562.  
  3563.   case 'o':
  3564. options:
  3565.     switch (cur_subopt("options c)ompression t)élécharger f)ouiner m)éthode s)ite")) {
  3566.     case '?':
  3567.     case 'h':
  3568.       cur_more(OptionsHelp);
  3569.       cur_dispmask();
  3570.       goto options;
  3571.  
  3572.     case 'c':
  3573.       setup_enumed(CompressOptHelp, CompressList, "compress");
  3574.       break;
  3575.  
  3576.     case 't':
  3577.       cur_editvar("dlpath", "Entrez le chemin de destination des fichiers"),
  3578.       cur_editvar("send", "Entrez la commande utile à l'envoi des fichiers, eg. 'sz'");
  3579.       setup_enumed(FlatOptHelp, FlatDlList, "flatdl");
  3580.       setup_enumed(ReadmeOptHelp, ReadmeDlList, "readmedl");
  3581.       setup_enumed(QuietOptHelp, QuietDlList, "quietdl");
  3582.       break;
  3583.  
  3584.     case 'f':
  3585.       setup_findmethod();
  3586.       break;
  3587.  
  3588.     case 'm':
  3589.       trans_close();
  3590.       e_freeall();
  3591.       setup_method();
  3592.       get_recent();
  3593.       newvisible();
  3594.       NoFilesString = "Utilisez v)ue ou f)ouiner pour visualiser les fichiers";
  3595.       break;
  3596.  
  3597.     case 's':
  3598.       if (trans_options())
  3599.         break;
  3600.       if (CdRom) {
  3601.         get_sitelocal();
  3602.         allvisible();
  3603.       } else {
  3604.         get_recent();
  3605.         newvisible();
  3606.       }
  3607.       break;
  3608.  
  3609.     default:
  3610.       noredraw = 1;
  3611.     }
  3612.     cur_nosubopt();
  3613.  
  3614.     break;
  3615.  
  3616.   case 'p':
  3617.     cur_status("Format étroit sur 80 colonnes, format large sur 132 colonnes");
  3618.     switch (cur_subopt("imprimer e)troit l)arge")) {
  3619.     case 'e':
  3620.       width = 1;
  3621.       break;
  3622.     case 'l':
  3623.       width = 2;
  3624.       break;
  3625.     }
  3626.     if (width) {
  3627.       cur_editvar("printer", "Nom du fichier ou imprimer les noms visibles");
  3628.       print_listing(width);
  3629.     }
  3630.     cur_nosubopt();
  3631.     noredraw = 1;
  3632.     break;
  3633.  
  3634.   case 'q':
  3635.     cur_cmdstr("je quitte (et sauve les fichiers config)");
  3636.     option_save(ConfigFile);
  3637.     exit_adt(0);
  3638.     break;
  3639.  
  3640.   case 'Q':
  3641.     cur_cmdstr("Je quitte (SANS sauver les fichiers de config)");
  3642.     exit_adt(0);
  3643.     break;
  3644.  
  3645.   case 'v':
  3646. view:
  3647.     switch (cur_subopt("voir t)out r)ep c)ache k)onnu l)imite m)arqué n)ouveau s)ite a)lterner")) {
  3648.     case '?':
  3649.       cur_more(ViewHelp);
  3650.       cur_dispmask();
  3651.       goto view;
  3652.  
  3653.     case 't':
  3654.       if (!GotComplete) {
  3655.     get_complete();
  3656.     allvisible();
  3657.       }
  3658.       break;
  3659.  
  3660.     case 'r':
  3661.       cur_status("Selectionner le répertoire à montrer");
  3662.       dirvisible(cur_getstring(buf));
  3663.       cur_status("");
  3664.       break;
  3665.  
  3666.     case 'c':
  3667.       cur_editvar("hide", "Entrez le répertoire à cacher en permanence");
  3668.       invisible();
  3669.       break;
  3670.  
  3671.     case 'k':
  3672.       allvisible();
  3673.       break;
  3674.  
  3675.     case 'l':
  3676.       cur_status("Entrez la chaine à comparer avec les descriptions");
  3677.       strlimit(cur_getstring(buf));
  3678.       cur_status("");
  3679.       break;
  3680.  
  3681.     case 'm':
  3682.       markedvisible();
  3683.       break;
  3684.  
  3685.     case 'n':
  3686.       get_recent();
  3687.       newvisible();
  3688.       break;
  3689.  
  3690.     case 's':
  3691.       if (!GotLocal) {
  3692.     get_sitelocal();
  3693.     cur_clear();
  3694.     cur_report("tri...");
  3695.     allvisible();
  3696.       }
  3697.       break;
  3698.  
  3699.     case 'a':
  3700.       togglevisible();
  3701.       break;
  3702.  
  3703.     default:
  3704.       noredraw = 1;
  3705.     }
  3706.  
  3707.     cur_nosubopt();
  3708.     break;
  3709.  
  3710.   case 'r':
  3711.     if (Vis->num) {
  3712.       ENTRY *e=Vis->list[Vis->current];
  3713.  
  3714.       mystrcpy(buf, e->dir);
  3715.       tackon(buf, get_readme(e));
  3716.       adt_connect (disp_status, e->status & 1);
  3717.       display_remote(buf, get_readme(e));
  3718.       adt_disconnect();
  3719.     }
  3720.     break;
  3721.  
  3722.   case 't':
  3723.     sorttype = 0;
  3724. sort:
  3725.     switch (cur_subopt("tri a)ge r)ep n)om t)aille")) {
  3726.     case '?':
  3727.       cur_more(SortHelp);
  3728.       cur_dispmask();
  3729.       goto sort;
  3730.     case 'a':
  3731.       sorttype = &sort_age;
  3732.       break;
  3733.     case 'r':
  3734.       sorttype = &sort_dir;
  3735.       break;
  3736.     case 'n':
  3737.       sorttype = &sort_name;
  3738.       break;
  3739.     case 't':
  3740.       sorttype = &sort_size;
  3741.       break;
  3742.     case 'A':
  3743.       sorttype = &sort_rage;
  3744.       break;
  3745.     case 'R':
  3746.       sorttype = &sort_rdir;
  3747.       break;
  3748.     case 'N':
  3749.       sorttype = &sort_rname;
  3750.       break;
  3751.     case 'T':
  3752.       sorttype = &sort_rsize;
  3753.       break;
  3754.     }
  3755.     if (sorttype) {
  3756.       cur_status("tri...");
  3757.       sort_list(Vis, sorttype);
  3758.       cur_dispfiles(Vis);
  3759.       cur_status("");
  3760.     }
  3761.     noredraw = 1;
  3762.     cur_nosubopt();
  3763.     break;
  3764.  
  3765.   case 'h':
  3766.   case '?':
  3767.     cur_more(MainHelp);
  3768.     break;
  3769.  
  3770.   case 'm':
  3771.   case 13: case 10:
  3772.     noredraw = 1;
  3773.     if (!Vis->num)
  3774.       break;
  3775.     cur_mark(Vis, 0);
  3776.     tagcurrent();
  3777.     cur_mark(Vis, 1);
  3778.     cur_moveto(Vis, Vis->current + 1);
  3779.     break;
  3780.  
  3781.   case 'M':
  3782.     tagall();
  3783.     break;
  3784.  
  3785.   default:
  3786.     noredraw = 1;
  3787.  
  3788.   }
  3789.  
  3790.   if (!noredraw)
  3791.     cur_dispmask();
  3792.  
  3793.   return 0;
  3794. }
  3795.  
  3796.  
  3797.  
  3798. int cur_mainloop()
  3799. {
  3800.   int c;
  3801.  
  3802.   refresh();
  3803.   cur_dispmask();
  3804.   refresh();
  3805.  
  3806.   while ((c = inp_getchr())) {
  3807.     cur_listnav(Vis, c);
  3808.     cur_cmdkeys(c);
  3809.     move(Y_COMMAND, X_COMMAND);
  3810.     refresh();
  3811.   }
  3812.  
  3813.   return 0;
  3814. }
  3815.  
  3816. int cur_cleanup()
  3817. {
  3818.   nocbreak();
  3819.   echo();
  3820.   endwin();
  3821. #ifndef AMIGA
  3822.   puts("");
  3823. #endif
  3824.   return 0;
  3825. }
  3826.  
  3827. int cur_getcmd()
  3828. {
  3829.   return getchr();
  3830. }
  3831.  
  3832.  
  3833. int cur_confirm(strings, retry)
  3834.   char **strings;
  3835.   int retry;
  3836. {
  3837.   int i, j, m = str_shift(str_longest(strings), COLS);
  3838.  
  3839.   for (i = 0; strings[i]; i++);
  3840.  
  3841.   clear();
  3842.  
  3843.   for (j = 0; j < i; j++) {
  3844.     move((LINES - i - 2) / 2 + j, m);
  3845.     addstr(strings[j]);
  3846.   }
  3847.  
  3848.   move((LINES - i - 2) / 2 + j + 1, m + str_longest(strings) - strlen("Appuyez sur une touche"));
  3849.   addstr("Appuyez sur une touche");
  3850.  
  3851.   refresh();
  3852.   inp_getchr();
  3853.  
  3854.   return 0;
  3855. }
  3856.  
  3857. int cur_refresh()
  3858. {
  3859.   refresh();
  3860.  
  3861.   return 0;
  3862. }
  3863.  
  3864. #endif
  3865.  
  3866. /*---------------------------------main program------------------------------*/
  3867. int init_vars()
  3868. {
  3869.   char *d, *t;
  3870.   int i;
  3871.  
  3872.   mystrcpy(HomeDir, (t = (char *) getenv("HOME")) ? t : "");
  3873.  
  3874.   if (*HomeDir) {
  3875.     d = UserName;
  3876.     for (i = 0; HomeDir[i]; i++)
  3877.       if (HomeDir[i] == '/')
  3878.     d = UserName;
  3879.       else
  3880.     *d++ = HomeDir[i];
  3881.     *d++ = 0;
  3882.   }
  3883. #ifdef AMIGA
  3884.   mystrcpy(ConfigFile, "S:.adtrc");
  3885. #else
  3886.   mystrcpy(ConfigFile, HomeDir);
  3887.   tackon(ConfigFile, ".adtrc");
  3888. #endif
  3889.  
  3890.   Alt->sort = Vis->sel = "";
  3891.   Alt->sort = Vis->sort = "";
  3892.   Alt->cmds = Vis->cmds = "téléa)chat f)ouiner h)elp o)ption imp)rime q)uit r)ead t)ri m)arque v)ue";
  3893.  
  3894.   Mark->sel = "Fichier à ramener";
  3895.   Mark->sort = "";
  3896.   Mark->cmds = "a)ction b)egin p)ath q)uit r)eadmes s)ubdirs v)erbose";
  3897.  
  3898.   return 0;
  3899. }
  3900.  
  3901. char recentbuf[100];
  3902. char *FirstConnectHelp[] = {
  3903.   "C'est la première fois que tu te connectes. Tu vas seulement voir les",
  3904.   "derniers 14 jours de dépôt. La prochaine fois, tu verras tous les",
  3905.   "fichiers envoyés depuis cette connexion",0
  3906. };
  3907.  
  3908. char *LongAgoHelp[] = {
  3909.   "Votre dernière connexion date de plus de 14 jours. Vous ne verrez donc"
  3910.   "que les 14 derniers jours. Si vous voulez tout voir faites, v)ue t)out",
  3911.   "et filtrez en conséquence.",0  
  3912. };
  3913.  
  3914. int get_list(title, name)
  3915.   char *title, *name;
  3916. {
  3917.   TEMPFILE tfh;
  3918.   char buf[250];
  3919.   char *packer = "";
  3920.   long amotd = 0, lmotd = 0, sites = 0;
  3921.  
  3922.   e_freeall();
  3923.  
  3924.   if (option_getnum("compress") == 1)
  3925.     packer = ".Z";
  3926.  
  3927.   if (option_getnum("compress") == 2)
  3928.     packer = ".gz";
  3929.  
  3930.   sprintf(buf, "info/adt/%s", name);
  3931.  
  3932.   disp_clear();
  3933.   disp_report(title);
  3934.  
  3935.   adt_connect(disp_report, STATUS_LOCAL);
  3936.  
  3937.   NoFilesString = "Je n'ai pas pu ramener le fichier Index.";
  3938.   trans_remopen(&tfh, buf, packer, disp_report);
  3939.  
  3940.   if (tfh.fh) {
  3941.  
  3942.     disp_report("Lecture de l'index");
  3943.     do {
  3944.       *parsebuf = 0;
  3945.       fgets(parsebuf, PBUFSIZE, tfh.fh);
  3946.       if (!mystrncmp(parsebuf, "#amotd=", 7))
  3947.     amotd = p_atoi(parsebuf + 7);
  3948.       if (!mystrncmp(parsebuf, "#lmotd=", 7))
  3949.     lmotd = p_atoi(parsebuf + 7);
  3950.       if (!mystrncmp(parsebuf, "#sites=", 7))
  3951.     sites = p_atoi(parsebuf + 7);
  3952.  
  3953.     } while (*parsebuf == '#');
  3954.  
  3955.     read_adt_v2(tfh.fh);
  3956.     tclose(&tfh);
  3957.  
  3958.   }
  3959.  
  3960.   if (!option_getnum("nomotd")) {
  3961.     if (amotd > option_getnum("amotd")) {
  3962.       disp_clear();
  3963.       disp_report("Attend Ya un nouveau message d'Aminet");
  3964.       display_remote("info/adt/aminet-motd","Aminet message du jour");
  3965.       option_setnum("amotd", amotd);
  3966.     }
  3967.     if (lmotd > option_getnum("lmotd")) {
  3968.       disp_clear();
  3969.       disp_report("Attend ya un message local du jour");
  3970.       display_remote("info/adt/local-motd","Message du jour de ce miroir");
  3971.       option_setnum("lmotd", lmotd);
  3972.     }
  3973.   }
  3974.   if (sites > option_getnum("sites")) {
  3975.     disp_clear();
  3976.     disp_report("Remise a jour des sites");
  3977.     trans_remopen(&tfh, "info/adt/sites", "", disp_status);
  3978.     if (tfh.fh) {
  3979.       option_loadfh(tfh.fh);
  3980.       tclose(&tfh);
  3981.     }
  3982.     option_setnum("sites", sites);
  3983.   }
  3984.  
  3985.   adt_disconnect();
  3986.  
  3987.   return 0;
  3988. }
  3989.  
  3990. int get_complete()
  3991. {
  3992.   if (!GotComplete)
  3993.     get_list("Téléchargement de tout l'index Aminet", "ADT_AMINET");
  3994.  
  3995.   GotComplete = GotLocal = GotRecent = 1;
  3996.  
  3997.   return 0;
  3998. }
  3999.  
  4000. int get_sitelocal()
  4001. {
  4002.   if (!GotLocal)
  4003.     get_list("Téléchargement de l'index local", "ADT_LOCAL");
  4004.  
  4005.   GotLocal = GotRecent = 1;
  4006.  
  4007.   return 0;
  4008. }
  4009.  
  4010.  
  4011. int get_recent()
  4012. {
  4013.   long age;
  4014.  
  4015.   if (GotRecent)
  4016.     return 0;
  4017.  
  4018.   GotRecent = 1;
  4019.  
  4020.   LastCall = myatoi(option_get("newest"));
  4021.   age = time(NULL) - LastCall;
  4022.  
  4023.   if (LastCall == 0) {
  4024.     disp_confirm(FirstConnectHelp, 0);
  4025.     get_list("Je ramène la liste des nouveaux fichiers", "ADT_RECENT_14");
  4026.   } else if (age < 7 * 86400) {
  4027.     get_list("Je ramène la liste des nouveaux fichiers", "ADT_RECENT_7");
  4028.   } else if (age < 14 * 86400) {
  4029.     get_list("Je ramène la liste des nouveaux fichiers", "ADT_RECENT_14");
  4030.   } else {
  4031.     disp_confirm(LongAgoHelp, 0);
  4032.     get_list("Je ramène la liste des nouveaux fichiers", "ADT_RECENT_14");
  4033.   }
  4034.  
  4035.   if (newesttime() > option_getnum("newest"))
  4036.     option_setnum("newest", newesttime());
  4037.  
  4038.   return 0;
  4039. }
  4040.  
  4041. int init_display()
  4042. {
  4043.   disp_init = cur_dispinit;
  4044.   disp_getchar = cur_getchar;
  4045.   disp_cleanup = cur_cleanup;
  4046.   disp_choice = cur_choice;
  4047.   disp_mainloop = cur_mainloop;
  4048.   disp_report = cur_report;
  4049.   disp_status = cur_status;
  4050.   disp_confirm = cur_confirm;
  4051.   disp_more = cur_more;
  4052.   disp_inputstr = cur_inputstr;
  4053.   disp_clear = cur_clear;
  4054.   disp_refresh = cur_refresh;
  4055.  
  4056.   disp_init();
  4057.  
  4058. #ifdef SIGINT
  4059.   signal (SIGINT, adt_breakcheck);
  4060. #endif
  4061.  
  4062.   return 0;
  4063. }
  4064.  
  4065.  
  4066. int init_config()
  4067. {
  4068.   if (option_load(ConfigFile) || trans_init()) {
  4069.  
  4070.     InitialSetup = 1;
  4071.     setup_method();
  4072.     InitialSetup = 0;
  4073.     option_save(ConfigFile);
  4074.  
  4075.   }
  4076.   return 0;
  4077. }
  4078.  
  4079. int show_usage()
  4080. {
  4081.   puts("Usage: adt               (voir les derniers fichiers depuis le dernier appel)");
  4082.   puts("       adt -f motif      (cherche le motif avec la methode configure)");
  4083.   puts("       adt -l            (montre les fichiers locaux)");
  4084.   puts("       adt -n            (pas de connection)");
  4085.   exit_adt(0);
  4086.   return 0;
  4087. }
  4088.  
  4089. int parse_commandline(argc, argv)
  4090.   int argc;
  4091.   char *argv[];
  4092. {
  4093.   if (argc <= 1) {
  4094.     if (CdRom) {
  4095.       get_sitelocal();
  4096.       allvisible();
  4097.     } else {
  4098.       get_recent();
  4099.       newvisible();
  4100.     }
  4101.     return 0;
  4102.   }
  4103.   if (argv[1][0] != '-' || !argv[1][1] || argv[1][2])
  4104.     show_usage();
  4105.  
  4106.   switch (argv[1][1]) {
  4107.   case 'f':
  4108.     if (argc != 3)
  4109.       show_usage();
  4110.     find_string(argv[2], cur_report);
  4111.     break;
  4112.  
  4113.   case 'l':
  4114.     if (argc != 2)
  4115.       show_usage();
  4116.     get_sitelocal();
  4117.     newvisible();
  4118.     break;
  4119.  
  4120.   case 'n':
  4121.     if (argc != 2)
  4122.       show_usage();
  4123.     NoFilesString="Utiliser o)ptions pour se connecter à un service/site";
  4124.     break;
  4125.  
  4126.   default:
  4127.     show_usage();
  4128.   }
  4129.  
  4130.   return 0;
  4131. }
  4132.  
  4133.  
  4134. int main(argc, argv)
  4135.   int argc;
  4136.   char *argv[];
  4137. {
  4138.   init_vars();
  4139.   init_display();
  4140.   init_config();
  4141.  
  4142.   parse_commandline(argc, argv);
  4143.   disp_mainloop();
  4144.  
  4145.   exit_adt(0);
  4146.   return 0;
  4147. }
  4148.  
  4149. TRANSFER TransferTypes[] =
  4150. {
  4151. #ifndef NO_BUILTIN_FTP
  4152.   "bftp",   "FTP fait-maison: Utiliser des routines ftp interne pour le téléchargement", bftp_init,
  4153. #endif
  4154. #ifndef NO_EXTERNAL_FTP
  4155.   "ftp",   "External FTP: Use the 'ftp' program to download files         ", xftp_init,
  4156. #endif
  4157.   "local", "Fichiers locaux : Accès à un collection de fichier Aminet  ", local_init,
  4158.   "cdrom", "CD-ROM          : Accès à un CD-ROM ou des fichiers non mis-à-jour   ", local_init,
  4159.   0, 0, 0
  4160. };
  4161.  
  4162.  
  4163. /* to delete: ftp.log, pad, recent, short */
  4164.  
  4165.  
  4166.  
  4167.  
  4168.  
  4169.  
  4170.  
  4171.  
  4172.  
  4173.  
  4174.  
  4175.  
  4176.  
  4177.  
  4178.  
  4179.